1
0
mirror of https://github.com/moparisthebest/curl synced 2024-08-13 17:03:50 -04:00

Move connection-oriented variables from the SessionHandle struct to the

connectdata struct. This will in theory enable us to do persistent connections
with SCP+SFTP, but currently the state machine always (and wrongly) cleanup
everything in the 'done' action instead of in 'disconnect'. Also did a bunch
of indent fixes, if () => if() and a few other source cleanups like added
comments etc.
This commit is contained in:
Daniel Stenberg 2007-11-05 09:30:45 +00:00
parent 51009a40b4
commit b9a7f4e502
2 changed files with 347 additions and 343 deletions

304
lib/ssh.c
View File

@ -377,7 +377,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
sshc->nextState = SSH_NO_STATE; sshc->nextState = SSH_NO_STATE;
sshc->actualCode = CURLE_OK; sshc->actualCode = CURLE_OK;
rc = libssh2_session_startup(sftp_scp->ssh_session, sock); rc = libssh2_session_startup(sshc->ssh_session, sock);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
@ -389,7 +389,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
} }
/* Set libssh2 to non-blocking, since cURL is all non-blocking */ /* Set libssh2 to non-blocking, since cURL is all non-blocking */
libssh2_session_set_blocking(sftp_scp->ssh_session, 0); libssh2_session_set_blocking(sshc->ssh_session, 0);
#ifdef CURL_LIBSSH2_DEBUG #ifdef CURL_LIBSSH2_DEBUG
/* /*
@ -398,7 +398,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
* whatever) is up to us. As for know not much is implemented, besides * whatever) is up to us. As for know not much is implemented, besides
* showing how to get the fingerprint. * showing how to get the fingerprint.
*/ */
fingerprint = libssh2_hostkey_hash(sftp_scp->ssh_session, fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
LIBSSH2_HOSTKEY_HASH_MD5); LIBSSH2_HOSTKEY_HASH_MD5);
/* The fingerprint points to static storage (!), don't free() it. */ /* The fingerprint points to static storage (!), don't free() it. */
@ -417,7 +417,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) == 32) strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) == 32)
{ {
char buf[33]; char buf[33];
host_public_key_md5 = libssh2_hostkey_hash(sftp_scp->ssh_session, host_public_key_md5 = libssh2_hostkey_hash(sshc->ssh_session,
LIBSSH2_HOSTKEY_HASH_MD5); LIBSSH2_HOSTKEY_HASH_MD5);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
snprintf(&buf[i*2], 3, "%02x", snprintf(&buf[i*2], 3, "%02x",
@ -449,15 +449,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
* experience. * experience.
* So always specify it here. * So always specify it here.
*/ */
sshc->authlist = libssh2_userauth_list(sftp_scp->ssh_session, sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
sftp_scp->user, sftp_scp->user,
strlen(sftp_scp->user)); strlen(sftp_scp->user));
if(!sshc->authlist) { if(!sshc->authlist) {
if ((err = libssh2_session_last_errno(sftp_scp->ssh_session)) == if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
break; break;
} else { }
else {
state(conn, SSH_SESSION_FREE); state(conn, SSH_SESSION_FREE);
sshc->actualCode = libssh2_session_error_to_CURLE(err); sshc->actualCode = libssh2_session_error_to_CURLE(err);
break; break;
@ -538,7 +539,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
case SSH_AUTH_PKEY: case SSH_AUTH_PKEY:
/* The function below checks if the files exists, no need to stat() here. /* The function below checks if the files exists, no need to stat() here.
*/ */
rc = libssh2_userauth_publickey_fromfile(sftp_scp->ssh_session, rc = libssh2_userauth_publickey_fromfile(sshc->ssh_session,
sftp_scp->user, sshc->rsa_pub, sftp_scp->user, sshc->rsa_pub,
sshc->rsa, sshc->passphrase); sshc->rsa, sshc->passphrase);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
@ -554,7 +555,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
sshc->authed = TRUE; sshc->authed = TRUE;
infof(data, "Initialized SSH public key authentication\n"); infof(data, "Initialized SSH public key authentication\n");
state(conn, SSH_AUTH_DONE); state(conn, SSH_AUTH_DONE);
} else { }
else {
state(conn, SSH_AUTH_PASS_INIT); state(conn, SSH_AUTH_PASS_INIT);
} }
break; break;
@ -569,7 +571,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_AUTH_PASS: case SSH_AUTH_PASS:
rc = libssh2_userauth_password(sftp_scp->ssh_session, sftp_scp->user, rc = libssh2_userauth_password(sshc->ssh_session, sftp_scp->user,
sftp_scp->passwd); sftp_scp->passwd);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
@ -578,7 +580,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
sshc->authed = TRUE; sshc->authed = TRUE;
infof(data, "Initialized password authentication\n"); infof(data, "Initialized password authentication\n");
state(conn, SSH_AUTH_DONE); state(conn, SSH_AUTH_DONE);
} else { }
else {
state(conn, SSH_AUTH_HOST_INIT); state(conn, SSH_AUTH_HOST_INIT);
} }
break; break;
@ -587,7 +590,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) && if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
(strstr(sshc->authlist, "hostbased") != NULL)) { (strstr(sshc->authlist, "hostbased") != NULL)) {
state(conn, SSH_AUTH_HOST); state(conn, SSH_AUTH_HOST);
} else { }
else {
state(conn, SSH_AUTH_KEY_INIT); state(conn, SSH_AUTH_KEY_INIT);
} }
break; break;
@ -600,14 +604,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
&& (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
state(conn, SSH_AUTH_KEY); state(conn, SSH_AUTH_KEY);
} else { }
else {
state(conn, SSH_AUTH_DONE); state(conn, SSH_AUTH_DONE);
} }
break; break;
case SSH_AUTH_KEY: case SSH_AUTH_KEY:
/* Authentication failed. Continue with keyboard-interactive now. */ /* Authentication failed. Continue with keyboard-interactive now. */
rc = libssh2_userauth_keyboard_interactive_ex(sftp_scp->ssh_session, rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
sftp_scp->user, sftp_scp->user,
strlen(sftp_scp->user), strlen(sftp_scp->user),
&kbd_callback); &kbd_callback);
@ -648,12 +653,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
/* /*
* Start the libssh2 sftp session * Start the libssh2 sftp session
*/ */
sftp_scp->sftp_session = libssh2_sftp_init(sftp_scp->ssh_session); sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
if (!sftp_scp->sftp_session) { if(!sshc->sftp_session) {
if (libssh2_session_last_errno(sftp_scp->ssh_session) == if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
break; break;
} else { }
else {
failf(data, "Failure initialising sftp session\n"); failf(data, "Failure initialising sftp session\n");
state(conn, SSH_SESSION_FREE); state(conn, SSH_SESSION_FREE);
sshc->actualCode = CURLE_FAILED_INIT; sshc->actualCode = CURLE_FAILED_INIT;
@ -670,7 +676,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
/* /*
* Get the "home" directory * Get the "home" directory
*/ */
rc = libssh2_sftp_realpath(sftp_scp->sftp_session, ".", rc = libssh2_sftp_realpath(sshc->sftp_session, ".",
tempHome, PATH_MAX-1); tempHome, PATH_MAX-1);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
@ -684,9 +690,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
sshc->actualCode = CURLE_OUT_OF_MEMORY; sshc->actualCode = CURLE_OUT_OF_MEMORY;
break; break;
} }
} else { }
else {
/* Return the error type */ /* Return the error type */
result = libssh2_sftp_last_error(sftp_scp->sftp_session); result = libssh2_sftp_last_error(sshc->sftp_session);
DEBUGF(infof(data, "error = %d\n", result)); DEBUGF(infof(data, "error = %d\n", result));
state(conn, SSH_STOP); state(conn, SSH_STOP);
break; break;
@ -785,7 +792,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
infof(data, "Sending quote commands\n"); infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.quote; sshc->quote_item = data->set.quote;
state(conn, SSH_SFTP_QUOTE); state(conn, SSH_SFTP_QUOTE);
} else { }
else {
state(conn, SSH_SFTP_TRANS_INIT); state(conn, SSH_SFTP_TRANS_INIT);
} }
break; break;
@ -795,7 +803,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
infof(data, "Sending quote commands\n"); infof(data, "Sending quote commands\n");
sshc->quote_item = data->set.postquote; sshc->quote_item = data->set.postquote;
state(conn, SSH_SFTP_QUOTE); state(conn, SSH_SFTP_QUOTE);
} else { }
else {
state(conn, SSH_STOP); state(conn, SSH_STOP);
} }
break; break;
@ -975,13 +984,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_QUOTE_STAT: case SSH_SFTP_QUOTE_STAT:
rc = libssh2_sftp_stat(sftp_scp->sftp_session, sshc->quote_path2, rc = libssh2_sftp_stat(sshc->sftp_session, sshc->quote_path2,
&sshc->quote_attrs); &sshc->quote_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc != 0) { /* get those attributes */ else if(rc != 0) { /* get those attributes */
err = libssh2_sftp_last_error(sftp_scp->sftp_session); err = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL; sshc->quote_path1 = NULL;
Curl_safefree(sshc->quote_path2); Curl_safefree(sshc->quote_path2);
@ -1041,12 +1050,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_QUOTE_SETSTAT: case SSH_SFTP_QUOTE_SETSTAT:
rc = libssh2_sftp_setstat(sftp_scp->sftp_session, sshc->quote_path2, rc = libssh2_sftp_setstat(sshc->sftp_session, sshc->quote_path2,
&sshc->quote_attrs); &sshc->quote_attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} else if(rc != 0) { } else if(rc != 0) {
err = libssh2_sftp_last_error(sftp_scp->sftp_session); err = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL; sshc->quote_path1 = NULL;
Curl_safefree(sshc->quote_path2); Curl_safefree(sshc->quote_path2);
@ -1061,13 +1070,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_QUOTE_SYMLINK: case SSH_SFTP_QUOTE_SYMLINK:
rc = libssh2_sftp_symlink(sftp_scp->sftp_session, sshc->quote_path1, rc = libssh2_sftp_symlink(sshc->sftp_session, sshc->quote_path1,
sshc->quote_path2); sshc->quote_path2);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc != 0) { else if(rc != 0) {
err = libssh2_sftp_last_error(sftp_scp->sftp_session); err = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL; sshc->quote_path1 = NULL;
Curl_safefree(sshc->quote_path2); Curl_safefree(sshc->quote_path2);
@ -1082,12 +1091,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_QUOTE_MKDIR: case SSH_SFTP_QUOTE_MKDIR:
rc = libssh2_sftp_mkdir(sftp_scp->sftp_session, sshc->quote_path1, 0755); rc = libssh2_sftp_mkdir(sshc->sftp_session, sshc->quote_path1, 0755);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc != 0) { else if(rc != 0) {
err = libssh2_sftp_last_error(sftp_scp->sftp_session); err = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL; sshc->quote_path1 = NULL;
failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err)); failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
@ -1099,12 +1108,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_QUOTE_RENAME: case SSH_SFTP_QUOTE_RENAME:
rc = libssh2_sftp_rename(sftp_scp->sftp_session, sshc->quote_path1, rc = libssh2_sftp_rename(sshc->sftp_session, sshc->quote_path1,
sshc->quote_path2); sshc->quote_path2);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} else if (rc != 0) { }
err = libssh2_sftp_last_error(sftp_scp->sftp_session); else if(rc != 0) {
err = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL; sshc->quote_path1 = NULL;
Curl_safefree(sshc->quote_path2); Curl_safefree(sshc->quote_path2);
@ -1118,12 +1128,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_QUOTE_RMDIR: case SSH_SFTP_QUOTE_RMDIR:
rc = libssh2_sftp_rmdir(sftp_scp->sftp_session, sshc->quote_path1); rc = libssh2_sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc != 0) { else if(rc != 0) {
err = libssh2_sftp_last_error(sftp_scp->sftp_session); err = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL; sshc->quote_path1 = NULL;
failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err)); failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
@ -1135,12 +1145,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_QUOTE_UNLINK: case SSH_SFTP_QUOTE_UNLINK:
rc = libssh2_sftp_unlink(sftp_scp->sftp_session, sshc->quote_path1); rc = libssh2_sftp_unlink(sshc->sftp_session, sshc->quote_path1);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc != 0) { else if(rc != 0) {
err = libssh2_sftp_last_error(sftp_scp->sftp_session); err = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path1);
sshc->quote_path1 = NULL; sshc->quote_path1 = NULL;
failf(data, "rm command failed: %s", sftp_libssh2_strerror(err)); failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
@ -1152,17 +1162,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_TRANS_INIT: case SSH_SFTP_TRANS_INIT:
if (data->set.upload) { if(data->set.upload)
state(conn, SSH_SFTP_UPLOAD_INIT); state(conn, SSH_SFTP_UPLOAD_INIT);
break; else {
} else { if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
if (sftp_scp->path[strlen(sftp_scp->path)-1] == '/') {
state(conn, SSH_SFTP_READDIR_INIT); state(conn, SSH_SFTP_READDIR_INIT);
break; else
} else {
state(conn, SSH_SFTP_DOWNLOAD_INIT); state(conn, SSH_SFTP_DOWNLOAD_INIT);
break;
}
} }
break; break;
@ -1173,16 +1179,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
* If this is not done the destination file will be named the * If this is not done the destination file will be named the
* same name as the last directory in the path. * same name as the last directory in the path.
*/ */
sftp_scp->sftp_handle = sshc->sftp_handle =
libssh2_sftp_open(sftp_scp->sftp_session, sftp_scp->path, libssh2_sftp_open(sshc->sftp_session, sftp_scp->path,
LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
data->set.new_file_perms); data->set.new_file_perms);
if (!sftp_scp->sftp_handle) { if(!sshc->sftp_handle) {
if (libssh2_session_last_errno(sftp_scp->ssh_session) == if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
break; break;
} else { }
err = libssh2_sftp_last_error(sftp_scp->sftp_session); else {
err = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Upload failed: %s", sftp_libssh2_strerror(err)); failf(data, "Upload failed: %s", sftp_libssh2_strerror(err));
if(sshc->secondCreateDirs) { if(sshc->secondCreateDirs) {
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
@ -1240,7 +1247,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
case SSH_SFTP_CREATE_DIRS_MKDIR: case SSH_SFTP_CREATE_DIRS_MKDIR:
/* 'mode' - parameter is preliminary - default to 0644 */ /* 'mode' - parameter is preliminary - default to 0644 */
rc = libssh2_sftp_mkdir(sftp_scp->sftp_session, sftp_scp->path, rc = libssh2_sftp_mkdir(sshc->sftp_session, sftp_scp->path,
data->set.new_directory_perms); data->set.new_directory_perms);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
@ -1254,7 +1261,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
* permission was denied (creation might succeed further * permission was denied (creation might succeed further
* down the path) - retry on unspecific FAILURE also * down the path) - retry on unspecific FAILURE also
*/ */
sftp_err = libssh2_sftp_last_error(sftp_scp->sftp_session); sftp_err = libssh2_sftp_last_error(sshc->sftp_session);
if((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) && if((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
(sftp_err != LIBSSH2_FX_FAILURE) && (sftp_err != LIBSSH2_FX_FAILURE) &&
(sftp_err != LIBSSH2_FX_PERMISSION_DENIED)) { (sftp_err != LIBSSH2_FX_PERMISSION_DENIED)) {
@ -1272,14 +1279,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
* This is a directory that we are trying to get, so produce a * This is a directory that we are trying to get, so produce a
* directory listing * directory listing
*/ */
sftp_scp->sftp_handle = libssh2_sftp_opendir(sftp_scp->sftp_session, sshc->sftp_handle = libssh2_sftp_opendir(sshc->sftp_session,
sftp_scp->path); sftp_scp->path);
if (!sftp_scp->sftp_handle) { if(!sshc->sftp_handle) {
if (libssh2_session_last_errno(sftp_scp->ssh_session) == if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
break; break;
} else { }
err = libssh2_sftp_last_error(sftp_scp->sftp_session); else {
err = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open directory for reading: %s", failf(data, "Could not open directory for reading: %s",
sftp_libssh2_strerror(err)); sftp_libssh2_strerror(err));
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
@ -1303,7 +1311,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_READDIR: case SSH_SFTP_READDIR:
sshc->readdir_len = libssh2_sftp_readdir_ex(sftp_scp->sftp_handle, sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
sshc->readdir_filename, sshc->readdir_filename,
PATH_MAX, PATH_MAX,
sshc->readdir_longentry, sshc->readdir_longentry,
@ -1380,11 +1388,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
} }
else if(sshc->readdir_len <= 0) { else if(sshc->readdir_len <= 0) {
err = libssh2_sftp_last_error(sftp_scp->sftp_session); err = libssh2_sftp_last_error(sshc->sftp_session);
sshc->actualCode = err; sshc->actualCode = err;
failf(data, "Could not open remote file for reading: %s :: %d", failf(data, "Could not open remote file for reading: %s :: %d",
sftp_libssh2_strerror(err), sftp_libssh2_strerror(err),
libssh2_session_last_errno(sftp_scp->ssh_session)); libssh2_session_last_errno(sshc->ssh_session));
Curl_safefree(sshc->readdir_filename); Curl_safefree(sshc->readdir_filename);
sshc->readdir_filename = NULL; sshc->readdir_filename = NULL;
Curl_safefree(sshc->readdir_longentry); Curl_safefree(sshc->readdir_longentry);
@ -1395,7 +1403,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_READDIR_LINK: case SSH_SFTP_READDIR_LINK:
sshc->readdir_len = libssh2_sftp_readlink(sftp_scp->sftp_session, sshc->readdir_len = libssh2_sftp_readlink(sshc->sftp_session,
sshc->readdir_linkPath, sshc->readdir_linkPath,
sshc->readdir_filename, sshc->readdir_filename,
PATH_MAX); PATH_MAX);
@ -1446,11 +1454,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_READDIR_DONE: case SSH_SFTP_READDIR_DONE:
if (libssh2_sftp_closedir(sftp_scp->sftp_handle) == if(libssh2_sftp_closedir(sshc->sftp_handle) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
sftp_scp->sftp_handle = NULL; sshc->sftp_handle = NULL;
Curl_safefree(sshc->readdir_filename); Curl_safefree(sshc->readdir_filename);
sshc->readdir_filename = NULL; sshc->readdir_filename = NULL;
Curl_safefree(sshc->readdir_longentry); Curl_safefree(sshc->readdir_longentry);
@ -1465,15 +1473,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
/* /*
* Work on getting the specified file * Work on getting the specified file
*/ */
sftp_scp->sftp_handle = sshc->sftp_handle =
libssh2_sftp_open(sftp_scp->sftp_session, sftp_scp->path, libssh2_sftp_open(sshc->sftp_session, sftp_scp->path,
LIBSSH2_FXF_READ, data->set.new_file_perms); LIBSSH2_FXF_READ, data->set.new_file_perms);
if (!sftp_scp->sftp_handle) { if(!sshc->sftp_handle) {
if (libssh2_session_last_errno(sftp_scp->ssh_session) == if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
break; break;
} else { }
err = libssh2_sftp_last_error(sftp_scp->sftp_session); else {
err = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open remote file for reading: %s", failf(data, "Could not open remote file for reading: %s",
sftp_libssh2_strerror(err)); sftp_libssh2_strerror(err));
state(conn, SSH_SFTP_CLOSE); state(conn, SSH_SFTP_CLOSE);
@ -1488,7 +1497,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
{ {
LIBSSH2_SFTP_ATTRIBUTES attrs; LIBSSH2_SFTP_ATTRIBUTES attrs;
rc = libssh2_sftp_stat(sftp_scp->sftp_session, sftp_scp->path, &attrs); rc = libssh2_sftp_stat(sshc->sftp_session, sftp_scp->path, &attrs);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
@ -1518,29 +1527,29 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SFTP_CLOSE: case SSH_SFTP_CLOSE:
if (sftp_scp->sftp_handle) { if(sshc->sftp_handle) {
rc = libssh2_sftp_close(sftp_scp->sftp_handle); rc = libssh2_sftp_close(sshc->sftp_handle);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc < 0) { else if(rc < 0) {
infof(data, "Failed to close libssh2 file\n"); infof(data, "Failed to close libssh2 file\n");
} }
sftp_scp->sftp_handle = NULL; sshc->sftp_handle = NULL;
} }
state(conn, SSH_SFTP_SHUTDOWN); state(conn, SSH_SFTP_SHUTDOWN);
break; break;
case SSH_SFTP_SHUTDOWN: case SSH_SFTP_SHUTDOWN:
if (sftp_scp->sftp_session) { if(sshc->sftp_session) {
rc = libssh2_sftp_shutdown(sftp_scp->sftp_session); rc = libssh2_sftp_shutdown(sshc->sftp_session);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc < 0) { else if(rc < 0) {
infof(data, "Failed to stop libssh2 sftp subsystem\n"); infof(data, "Failed to stop libssh2 sftp subsystem\n");
} }
sftp_scp->sftp_session = NULL; sshc->sftp_session = NULL;
} }
Curl_safefree(sftp_scp->path); Curl_safefree(sftp_scp->path);
@ -1573,19 +1582,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
* not done the destination file will be named the same name as the last * not done the destination file will be named the same name as the last
* directory in the path. * directory in the path.
*/ */
sftp_scp->ssh_channel = sshc->ssh_channel =
libssh2_scp_send_ex(sftp_scp->ssh_session, sftp_scp->path, libssh2_scp_send_ex(sshc->ssh_session, sftp_scp->path,
data->set.new_file_perms, data->set.new_file_perms,
data->set.infilesize, 0, 0); data->set.infilesize, 0, 0);
if (!sftp_scp->ssh_channel) { if(!sshc->ssh_channel) {
if (libssh2_session_last_errno(sftp_scp->ssh_session) == if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
break; break;
} else { } else {
int ssh_err; int ssh_err;
char *err_msg; char *err_msg;
ssh_err = libssh2_session_last_error(sftp_scp->ssh_session, ssh_err = libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0); &err_msg, NULL, 0);
err = libssh2_session_error_to_CURLE(ssh_err); err = libssh2_session_error_to_CURLE(ssh_err);
failf(conn->data, "%s", err_msg); failf(conn->data, "%s", err_msg);
@ -1617,17 +1626,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
curl_off_t bytecount; curl_off_t bytecount;
memset(&sb, 0, sizeof(struct stat)); memset(&sb, 0, sizeof(struct stat));
sftp_scp->ssh_channel = libssh2_scp_recv(sftp_scp->ssh_session, sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
sftp_scp->path, &sb); sftp_scp->path, &sb);
if (!sftp_scp->ssh_channel) { if(!sshc->ssh_channel) {
if (libssh2_session_last_errno(sftp_scp->ssh_session) == if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) { LIBSSH2_ERROR_EAGAIN) {
break; break;
} else { } else {
int ssh_err; int ssh_err;
char *err_msg; char *err_msg;
ssh_err = libssh2_session_last_error(sftp_scp->ssh_session, ssh_err = libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0); &err_msg, NULL, 0);
err = libssh2_session_error_to_CURLE(ssh_err); err = libssh2_session_error_to_CURLE(ssh_err);
failf(conn->data, "%s", err_msg); failf(conn->data, "%s", err_msg);
@ -1661,8 +1670,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SCP_SEND_EOF: case SSH_SCP_SEND_EOF:
if (sftp_scp->ssh_channel) { if(sshc->ssh_channel) {
rc = libssh2_channel_send_eof(sftp_scp->ssh_channel); rc = libssh2_channel_send_eof(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
@ -1674,8 +1683,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SCP_WAIT_EOF: case SSH_SCP_WAIT_EOF:
if (sftp_scp->ssh_channel) { if(sshc->ssh_channel) {
rc = libssh2_channel_wait_eof(sftp_scp->ssh_channel); rc = libssh2_channel_wait_eof(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
@ -1687,8 +1696,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SCP_WAIT_CLOSE: case SSH_SCP_WAIT_CLOSE:
if (sftp_scp->ssh_channel) { if(sshc->ssh_channel) {
rc = libssh2_channel_wait_closed(sftp_scp->ssh_channel); rc = libssh2_channel_wait_closed(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
@ -1700,36 +1709,36 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SCP_CHANNEL_FREE: case SSH_SCP_CHANNEL_FREE:
if (sftp_scp->ssh_channel) { if(sshc->ssh_channel) {
rc = libssh2_channel_free(sftp_scp->ssh_channel); rc = libssh2_channel_free(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc < 0) { else if(rc < 0) {
infof(data, "Failed to free libssh2 scp subsystem\n"); infof(data, "Failed to free libssh2 scp subsystem\n");
} }
sftp_scp->ssh_channel = NULL; sshc->ssh_channel = NULL;
} }
state(conn, SSH_SESSION_DISCONECT); state(conn, SSH_SESSION_DISCONECT);
break; break;
case SSH_CHANNEL_CLOSE: case SSH_CHANNEL_CLOSE:
if (sftp_scp->ssh_channel) { if(sshc->ssh_channel) {
rc = libssh2_channel_close(sftp_scp->ssh_channel); rc = libssh2_channel_close(sshc->ssh_channel);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc < 0) { else if(rc < 0) {
infof(data, "Failed to stop libssh2 channel subsystem\n"); infof(data, "Failed to stop libssh2 channel subsystem\n");
} }
sftp_scp->ssh_channel = NULL; sshc->ssh_channel = NULL;
} }
state(conn, SSH_SESSION_DISCONECT); state(conn, SSH_SESSION_DISCONECT);
break; break;
case SSH_SESSION_DISCONECT: case SSH_SESSION_DISCONECT:
if (sftp_scp->ssh_session) { if(sshc->ssh_session) {
rc = libssh2_session_disconnect(sftp_scp->ssh_session, "Shutdown"); rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
@ -1748,15 +1757,15 @@ static CURLcode ssh_statemach_act(struct connectdata *conn)
break; break;
case SSH_SESSION_FREE: case SSH_SESSION_FREE:
if (sftp_scp->ssh_session) { if(sshc->ssh_session) {
rc = libssh2_session_free(sftp_scp->ssh_session); rc = libssh2_session_free(sshc->ssh_session);
if(rc == LIBSSH2_ERROR_EAGAIN) { if(rc == LIBSSH2_ERROR_EAGAIN) {
break; break;
} }
else if(rc < 0) { else if(rc < 0) {
infof(data, "Failed to free libssh2 session\n"); infof(data, "Failed to free libssh2 session\n");
} }
sftp_scp->ssh_session = NULL; sshc->ssh_session = NULL;
} }
sshc->nextState = SSH_NO_STATE; sshc->nextState = SSH_NO_STATE;
state(conn, SSH_STOP); state(conn, SSH_STOP);
@ -1827,11 +1836,6 @@ static CURLcode ssh_init(struct connectdata *conn)
ssh->errorstr = NULL; ssh->errorstr = NULL;
ssh->ssh_session = NULL;
ssh->ssh_channel = NULL;
ssh->sftp_session = NULL;
ssh->sftp_handle = NULL;
return CURLE_OK; return CURLE_OK;
} }
@ -1841,11 +1845,20 @@ static CURLcode ssh_init(struct connectdata *conn)
*/ */
static CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done) static CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
{ {
struct SSHPROTO *ssh; struct ssh_conn *ssh;
curl_socket_t sock; curl_socket_t sock;
CURLcode result; CURLcode result;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
#if 0
/* Due to the fact that the state machine always cleans up and kills all
handles, we cannot currently re-use SCP or SFTP connections... */
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
conn->bits.close = FALSE;
#endif
/* If there already is a protocol-specific struct allocated for this /* If there already is a protocol-specific struct allocated for this
sessionhandle, deal with it */ sessionhandle, deal with it */
Curl_reset_reqproto(conn); Curl_reset_reqproto(conn);
@ -1854,7 +1867,7 @@ static CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
if(result) if(result)
return result; return result;
ssh = data->reqdata.proto.ssh; ssh = &conn->proto.sshc;
#ifdef CURL_LIBSSH2_DEBUG #ifdef CURL_LIBSSH2_DEBUG
if(ssh->user) { if(ssh->user) {
@ -1975,14 +1988,6 @@ static CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
res = scp_perform(conn, &connected, done); res = scp_perform(conn, &connected, done);
if (CURLE_OK == res) {
if (!done) {
/* the DO phase has not completed yet */
return CURLE_OK;
}
}
return res; return res;
} }
@ -1999,11 +2004,13 @@ static CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
/* run the state-machine */ /* run the state-machine */
if(conn->data->state.used_interface == Curl_if_multi) { if(conn->data->state.used_interface == Curl_if_multi) {
result = Curl_ssh_multi_statemach(conn, &done); result = Curl_ssh_multi_statemach(conn, &done);
} else { }
else {
result = ssh_easy_statemach(conn); result = ssh_easy_statemach(conn);
done = TRUE; done = TRUE;
} }
} else { }
else {
result = status; result = status;
done = TRUE; done = TRUE;
} }
@ -2023,18 +2030,14 @@ ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
void *mem, size_t len) void *mem, size_t len)
{ {
ssize_t nwrite; ssize_t nwrite;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_write() returns int /* libssh2_channel_write() returns int! */
*
* NOTE: we should not store nor rely on connection-related data to be
* in the SessionHandle struct
*/
nwrite = (ssize_t) nwrite = (ssize_t)
libssh2_channel_write(conn->data->reqdata.proto.ssh->ssh_channel, libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
mem, len);
if(nwrite == LIBSSH2_ERROR_EAGAIN) if(nwrite == LIBSSH2_ERROR_EAGAIN)
return 0; return 0;
(void)sockindex;
return nwrite; return nwrite;
} }
@ -2048,14 +2051,9 @@ ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
ssize_t nread; ssize_t nread;
(void)sockindex; /* we only support SCP on the fixed known primary socket */ (void)sockindex; /* we only support SCP on the fixed known primary socket */
/* libssh2_channel_read() returns int /* libssh2_channel_read() returns int */
*
* NOTE: we should not store nor rely on connection-related data to be
* in the SessionHandle struct
*/
nread = (ssize_t) nread = (ssize_t)
libssh2_channel_read(conn->data->reqdata.proto.ssh->ssh_channel, libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
mem, len);
return nread; return nread;
} }
@ -2089,7 +2087,8 @@ CURLcode sftp_perform(struct connectdata *conn,
/* run the state-machine */ /* run the state-machine */
if(conn->data->state.used_interface == Curl_if_multi) { if(conn->data->state.used_interface == Curl_if_multi) {
result = Curl_ssh_multi_statemach(conn, dophase_done); result = Curl_ssh_multi_statemach(conn, dophase_done);
} else { }
else {
result = ssh_easy_statemach(conn); result = ssh_easy_statemach(conn);
*dophase_done = TRUE; /* with the easy interface we are done here */ *dophase_done = TRUE; /* with the easy interface we are done here */
} }
@ -2131,9 +2130,8 @@ static CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
* Curl_ssh_connect() function. * Curl_ssh_connect() function.
*/ */
res = ssh_init(conn); res = ssh_init(conn);
if (res) { if(res)
return res; return res;
}
data->reqdata.size = -1; /* make sure this is unknown at this point */ data->reqdata.size = -1; /* make sure this is unknown at this point */
@ -2169,18 +2167,19 @@ static CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
if(!status && !premature && conn->data->set.postquote) { if(!status && !premature && conn->data->set.postquote) {
sshc->nextState = SSH_SFTP_CLOSE; sshc->nextState = SSH_SFTP_CLOSE;
state(conn, SSH_SFTP_POSTQUOTE_INIT); state(conn, SSH_SFTP_POSTQUOTE_INIT);
} else {
state(conn, SSH_SFTP_CLOSE);
} }
else
state(conn, SSH_SFTP_CLOSE);
/* run the state-machine */ /* run the state-machine */
if (conn->data->state.used_interface == Curl_if_multi) { if(conn->data->state.used_interface == Curl_if_multi)
result = Curl_ssh_multi_statemach(conn, &done); result = Curl_ssh_multi_statemach(conn, &done);
} else { else {
result = ssh_easy_statemach(conn); result = ssh_easy_statemach(conn);
done = TRUE; done = TRUE;
} }
} else { }
else {
result = status; result = status;
done = TRUE; done = TRUE;
} }
@ -2194,25 +2193,24 @@ static CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
return result; return result;
} }
/* return number of received (decrypted) bytes */ /* return number of sent bytes */
ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex, ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
void *mem, size_t len) void *mem, size_t len)
{ {
ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14 ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
but is changed to ssize_t in 0.15! */ but is changed to ssize_t in 0.15. These days we don't
support libssh2 0.15*/
(void)sockindex;
nwrite = (ssize_t) nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
libssh2_sftp_write(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
if(nwrite == LIBSSH2_ERROR_EAGAIN) if(nwrite == LIBSSH2_ERROR_EAGAIN)
return 0; return 0;
(void)sockindex;
return nwrite; return nwrite;
} }
/* /*
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return * Return number of received (decrypted) bytes
* a regular CURLcode value.
*/ */
ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex, ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len) char *mem, size_t len)
@ -2220,9 +2218,7 @@ ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
ssize_t nread; ssize_t nread;
(void)sockindex; (void)sockindex;
/* libssh2_sftp_read() returns size_t !*/ nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
nread = (ssize_t)
libssh2_sftp_read(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
return nread; return nread;
} }

View File

@ -485,6 +485,10 @@ typedef enum {
SSH_LAST /* never used */ SSH_LAST /* never used */
} sshstate; } sshstate;
/* this struct is used in the HandleData struct which is part of the
SessionHandle, which means this is used on a per-easy handle basis.
Everything that is strictly related to a connection is banned from this
struct. */
struct SSHPROTO { struct SSHPROTO {
curl_off_t *bytecountp; curl_off_t *bytecountp;
char *user; char *user;
@ -492,12 +496,6 @@ struct SSHPROTO {
char *path; /* the path we operate on */ char *path; /* the path we operate on */
char *homedir; char *homedir;
char *errorstr; char *errorstr;
#ifdef USE_LIBSSH2
LIBSSH2_SESSION *ssh_session; /* Secure Shell session */
LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
LIBSSH2_SFTP *sftp_session; /* SFTP handle */
LIBSSH2_SFTP_HANDLE *sftp_handle;
#endif /* USE_LIBSSH2 */
}; };
/* ssh_conn is used for struct connection-oriented data in the connectdata /* ssh_conn is used for struct connection-oriented data in the connectdata
@ -505,25 +503,35 @@ struct SSHPROTO {
struct ssh_conn { struct ssh_conn {
const char *authlist; /* List of auth. methods, managed by libssh2 */ const char *authlist; /* List of auth. methods, managed by libssh2 */
#ifdef USE_LIBSSH2 #ifdef USE_LIBSSH2
const char *passphrase; const char *passphrase; /* passphrase to use */
char *rsa_pub; char *rsa_pub; /* path name */
char *rsa; char *rsa; /* path name */
bool authed; bool authed; /* the connection has been authenticated fine */
sshstate state; /* always use ssh.c:state() to change state! */ sshstate state; /* always use ssh.c:state() to change state! */
sshstate nextState; /* the state to goto after stopping */ sshstate nextState; /* the state to goto after stopping */
CURLcode actualCode; /* the actual error code */ CURLcode actualCode; /* the actual error code */
struct curl_slist *quote_item; struct curl_slist *quote_item; /* for the quote option */
char *quote_path1; char *quote_path1; /* two generic pointers for the QUOTE stuff */
char *quote_path2; char *quote_path2;
LIBSSH2_SFTP_ATTRIBUTES quote_attrs; LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */
/* Here's a set of struct members used by the SFTP_READDIR state */
LIBSSH2_SFTP_ATTRIBUTES readdir_attrs; LIBSSH2_SFTP_ATTRIBUTES readdir_attrs;
char *readdir_filename; char *readdir_filename;
char *readdir_longentry; char *readdir_longentry;
int readdir_len, readdir_totalLen, readdir_currLen; int readdir_len, readdir_totalLen, readdir_currLen;
char *readdir_line; char *readdir_line;
char *readdir_linkPath; char *readdir_linkPath;
int secondCreateDirs; /* end of READDIR stuff */
char *slash_pos;
int secondCreateDirs; /* counter use by the code to see if the
second attempt has been made to change
to/create a directory */
char *slash_pos; /* used by the SFTP_CREATE_DIRS state */
LIBSSH2_SESSION *ssh_session; /* Secure Shell session */
LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */
LIBSSH2_SFTP *sftp_session; /* SFTP handle */
LIBSSH2_SFTP_HANDLE *sftp_handle;
#endif /* USE_LIBSSH2 */ #endif /* USE_LIBSSH2 */
}; };