aboutsummaryrefslogtreecommitdiff
path: root/lib/ssh.c
diff options
context:
space:
mode:
authorJames Housley <jim@thehousleys.net>2007-06-08 16:02:57 +0000
committerJames Housley <jim@thehousleys.net>2007-06-08 16:02:57 +0000
commitcd4e6fbcacc41de714a8f485d64789f013f755d7 (patch)
tree778a8703a72c4c460811c9442b714795acab474b /lib/ssh.c
parent2fd2ca9dac58afb8663d8a1a3801aa254f855462 (diff)
Fix to work with the latest CVS version of libssh2
* As of (LIBSSH2_APINO >= 200706012030) there are not *nb() functions * As of (LIBSSH2_APINO >= 200706012030) most libssh2_*() functions can return LIBSSH2_ERROR_EAGAIN to indicate that the call would block. To make the code work as previously, blocking, all the code has been updated so that when (LIBSSH2_APINO >= 200706012030) it loops simulating blocking. This allows the existing code to function and not hold up the upcoming release.
Diffstat (limited to 'lib/ssh.c')
-rw-r--r--lib/ssh.c592
1 files changed, 464 insertions, 128 deletions
diff --git a/lib/ssh.c b/lib/ssh.c
index 5bba63986..184a74b69 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -310,13 +310,27 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
Curl_safefree(working_path);
return CURLE_FAILED_INIT;
}
+
+#if (LIBSSH2_APINO >= 200706012030)
+ /* Set libssh2 to non-blocking, since cURL is all non-blocking */
+ libssh2_session_set_blocking(ssh->ssh_session, 0);
+#endif /* LIBSSH2_APINO >= 200706012030 */
#ifdef CURL_LIBSSH2_DEBUG
- libssh2_trace(ssh->ssh_session, LIBSSH2_TRACE_CONN|LIBSSH2_TRACE_TRANS|LIBSSH2_TRACE_KEX|LIBSSH2_TRACE_AUTH|LIBSSH2_TRACE_SCP|LIBSSH2_TRACE_SFTP|LIBSSH2_TRACE_ERROR|LIBSSH2_TRACE_PUBLICKEY);
+ libssh2_trace(ssh->ssh_session, LIBSSH2_TRACE_CONN|LIBSSH2_TRACE_TRANS|
+ LIBSSH2_TRACE_KEX|LIBSSH2_TRACE_AUTH|LIBSSH2_TRACE_SCP|
+ LIBSSH2_TRACE_SFTP|LIBSSH2_TRACE_ERROR|
+ LIBSSH2_TRACE_PUBLICKEY);
infof(data, "SSH socket: %d\n", sock);
#endif /* CURL_LIBSSH2_DEBUG */
- if (libssh2_session_startup(ssh->ssh_session, sock)) {
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((i = libssh2_session_startup(ssh->ssh_session, sock)) ==
+ LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
+ i = libssh2_session_startup(ssh->ssh_session, sock);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
+ if (i) {
failf(data, "Failure establishing ssh session");
libssh2_session_free(ssh->ssh_session);
ssh->ssh_session = NULL;
@@ -353,6 +367,20 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
* presumably with a blank username. That won't work in my experience.
* So always specify it here.
*/
+#if (LIBSSH2_APINO >= 200706012030)
+ do {
+ authlist = libssh2_userauth_list(ssh->ssh_session, ssh->user,
+ strlen(ssh->user));
+
+ if (!authlist && (libssh2_session_last_errno(ssh->ssh_session) !=
+ LIBSSH2_ERROR_EAGAIN)) {
+ libssh2_session_free(ssh->ssh_session);
+ ssh->ssh_session = NULL;
+ Curl_safefree(working_path);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ } while (!authlist);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
authlist = libssh2_userauth_list(ssh->ssh_session, ssh->user,
strlen(ssh->user));
if (!authlist) {
@@ -361,6 +389,7 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
Curl_safefree(working_path);
return CURLE_OUT_OF_MEMORY;
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
infof(data, "SSH authentication methods available: %s\n", authlist);
/*
@@ -402,8 +431,16 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
if (rsa_pub[0]) {
/* The function below checks if the files exists, no need to stat() here.
*/
- if (libssh2_userauth_publickey_fromfile(ssh->ssh_session, ssh->user,
- rsa_pub, rsa, passphrase) == 0) {
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((i = libssh2_userauth_publickey_fromfile(ssh->ssh_session,
+ ssh->user, rsa_pub,
+ rsa, passphrase)) ==
+ LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
+ i = libssh2_userauth_publickey_fromfile(ssh->ssh_session, ssh->user,
+ rsa_pub, rsa, passphrase);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
+ if (i == 0) {
authed = TRUE;
infof(conn->data, "Initialized SSH public key authentication\n");
}
@@ -412,7 +449,14 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
if (!authed &&
(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
(strstr(authlist, "password") != NULL)) {
- if (!libssh2_userauth_password(ssh->ssh_session, ssh->user, ssh->passwd)) {
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((i = libssh2_userauth_password(ssh->ssh_session, ssh->user,
+ ssh->passwd)) ==
+ LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
+ i = libssh2_userauth_password(ssh->ssh_session, ssh->user, ssh->passwd);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
+ if (i == 0) {
authed = TRUE;
infof(conn->data, "Initialized password authentication\n");
}
@@ -423,9 +467,18 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
if (!authed && (data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
&& (strstr(authlist, "keyboard-interactive") != NULL)) {
/* Authentication failed. Continue with keyboard-interactive now. */
- if (libssh2_userauth_keyboard_interactive_ex(ssh->ssh_session, ssh->user,
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((i = libssh2_userauth_keyboard_interactive_ex(ssh->ssh_session,
+ ssh->user,
+ strlen(ssh->user),
+ &kbd_callback)) ==
+ LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
+ i = libssh2_userauth_keyboard_interactive_ex(ssh->ssh_session, ssh->user,
strlen(ssh->user),
- &kbd_callback) == 0) {
+ &kbd_callback);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
+ if (i == 0) {
authed = TRUE;
infof(conn->data, "Initialized keyboard interactive authentication\n");
}
@@ -453,6 +506,19 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
/*
* Start the libssh2 sftp session
*/
+#if (LIBSSH2_APINO >= 200706012030)
+ do {
+ ssh->sftp_session = libssh2_sftp_init(ssh->ssh_session);
+ if (!ssh->sftp_session && (libssh2_session_last_errno(ssh->ssh_session) !=
+ LIBSSH2_ERROR_EAGAIN)) {
+ failf(data, "Failure initialising sftp session\n");
+ libssh2_session_free(ssh->ssh_session);
+ ssh->ssh_session = NULL;
+ Curl_safefree(working_path);
+ return CURLE_FAILED_INIT;
+ }
+ } while (!ssh->sftp_session);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
ssh->sftp_session = libssh2_sftp_init(ssh->ssh_session);
if (ssh->sftp_session == NULL) {
failf(data, "Failure initialising sftp session\n");
@@ -461,11 +527,18 @@ CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
Curl_safefree(working_path);
return CURLE_FAILED_INIT;
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
/*
* Get the "home" directory
*/
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((i = libssh2_sftp_realpath(ssh->sftp_session, ".",
+ tempHome, PATH_MAX-1)) ==
+ LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
i = libssh2_sftp_realpath(ssh->sftp_session, ".", tempHome, PATH_MAX-1);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
if (i > 0) {
/* It seems that this string is not always NULL terminated */
tempHome[i] = '\0';
@@ -572,6 +645,21 @@ CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
* the destination file will be named the same name as the last directory
* in the path.
*/
+#if (LIBSSH2_APINO >= 200706012030)
+ do {
+ scp->ssh_channel = libssh2_scp_send_ex(scp->ssh_session, scp->path,
+ LIBSSH2_SFTP_S_IRUSR|
+ LIBSSH2_SFTP_S_IWUSR|
+ LIBSSH2_SFTP_S_IRGRP|
+ LIBSSH2_SFTP_S_IROTH,
+ conn->data->set.infilesize, 0, 0);
+ if (!scp->ssh_channel &&
+ (libssh2_session_last_errno(scp->ssh_session) !=
+ LIBSSH2_ERROR_EAGAIN)) {
+ return CURLE_FAILED_INIT;
+ }
+ } while (!scp->ssh_channel);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
scp->ssh_channel = libssh2_scp_send_ex(scp->ssh_session, scp->path,
LIBSSH2_SFTP_S_IRUSR|
LIBSSH2_SFTP_S_IWUSR|
@@ -580,6 +668,7 @@ CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
conn->data->set.infilesize, 0, 0);
if (!scp->ssh_channel)
return CURLE_FAILED_INIT;
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
/* upload data */
res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
@@ -591,6 +680,22 @@ CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
*/
curl_off_t bytecount;
memset(&sb, 0, sizeof(struct stat));
+#if (LIBSSH2_APINO >= 200706012030)
+ do {
+ scp->ssh_channel = libssh2_scp_recv(scp->ssh_session, scp->path, &sb);
+ if (!scp->ssh_channel &&
+ (libssh2_session_last_errno(scp->ssh_session) !=
+ LIBSSH2_ERROR_EAGAIN)) {
+ if ((sb.st_mode == 0) && (sb.st_atime == 0) && (sb.st_mtime == 0) &&
+ (sb.st_size == 0)) {
+ /* Since sb is still empty, it is likely the file was not found */
+ return CURLE_REMOTE_FILE_NOT_FOUND;
+ }
+ return libssh2_session_error_to_CURLE(
+ libssh2_session_last_error(scp->ssh_session, NULL, NULL, 0));
+ }
+ } while (!scp->ssh_channel);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
scp->ssh_channel = libssh2_scp_recv(scp->ssh_session, scp->path, &sb);
if (!scp->ssh_channel) {
if ((sb.st_mode == 0) && (sb.st_atime == 0) && (sb.st_mtime == 0) &&
@@ -601,6 +706,7 @@ CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
return libssh2_session_error_to_CURLE(
libssh2_session_last_error(scp->ssh_session, NULL, NULL, 0));
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
/* download data */
bytecount = (curl_off_t) sb.st_size;
conn->data->reqdata.maxdownload = (curl_off_t) sb.st_size;
@@ -614,6 +720,7 @@ CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
bool premature)
{
+ int rc;
struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
(void)premature; /* not used */
@@ -621,6 +728,25 @@ CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
scp->path = NULL;
if (scp->ssh_channel) {
+#if (LIBSSH2_APINO >= 200706012030)
+ if (conn->data->set.upload) {
+ while ((rc = libssh2_channel_send_eof(scp->ssh_channel)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (rc) {
+ infof(conn->data, "Failed to send libssh2 channel EOF\n");
+ }
+ while ((rc = libssh2_channel_wait_eof(scp->ssh_channel)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (rc) {
+ infof(conn->data, "Failed to get channel EOF\n");
+ }
+ while ((rc = libssh2_channel_wait_closed(scp->ssh_channel)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (rc) {
+ infof(conn->data, "Channel failed to close\n");
+ }
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
if (conn->data->set.upload &&
libssh2_channel_send_eof(scp->ssh_channel) < 0) {
infof(conn->data, "Failed to send libssh2 channel EOF\n");
@@ -628,10 +754,16 @@ CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
if (libssh2_channel_close(scp->ssh_channel) < 0) {
infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
}
if (scp->ssh_session) {
+#if (LIBSSH2_APINO >= 200706012030)
+ while (libssh2_session_disconnect(scp->ssh_session, "Shutdown") ==
+ LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
libssh2_session_disconnect(scp->ssh_session, "Shutdown");
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
libssh2_session_free(scp->ssh_session);
scp->ssh_session = NULL;
}
@@ -656,7 +788,7 @@ ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
* NOTE: we should not store nor rely on connection-related data to be
* in the SessionHandle struct
*/
-#ifdef LIBSSH2CHANNEL_EAGAIN
+#if defined(LIBSSH2CHANNEL_EAGAIN) && (LIBSSH2_APINO < 200706012030)
nwrite = (ssize_t)
libssh2_channel_writenb(conn->data->reqdata.proto.ssh->ssh_channel,
mem, len);
@@ -685,7 +817,7 @@ ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
* in the SessionHandle struct
*/
-#ifdef LIBSSH2CHANNEL_EAGAIN
+#if defined(LIBSSH2CHANNEL_EAGAIN) && (LIBSSH2_APINO < 200706012030)
/* we prefer the non-blocking API but that didn't exist previously */
nread = (ssize_t)
libssh2_channel_readnb(conn->data->reqdata.proto.ssh->ssh_channel,
@@ -711,6 +843,7 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
curl_off_t bytecount = 0;
char *buf = data->state.buffer;
unsigned long err = 0;
+ int rc;
*done = TRUE; /* unconditionally */
@@ -729,6 +862,23 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
* If this is not done the destination file will be named the
* same name as the last directory in the path.
*/
+#if (LIBSSH2_APINO >= 200706012030)
+ do {
+ sftp->sftp_handle =
+ libssh2_sftp_open(sftp->sftp_session, sftp->path,
+ LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
+ LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
+ LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
+ if (!sftp->sftp_handle &&
+ (libssh2_session_last_errno(sftp->ssh_session) !=
+ LIBSSH2_ERROR_EAGAIN)) {
+ err = libssh2_sftp_last_error(sftp->sftp_session);
+ failf(conn->data, "Could not open remote file for writing: %s",
+ sftp_libssh2_strerror(err));
+ return sftp_libssh2_error_to_CURLE(err);
+ }
+ } while (!sftp->sftp_handle);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
sftp->sftp_handle =
libssh2_sftp_open(sftp->sftp_session, sftp->path,
LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
@@ -740,6 +890,7 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
sftp_libssh2_strerror(err));
return sftp_libssh2_error_to_CURLE(err);
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
/* upload data */
res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
@@ -758,6 +909,20 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
int len, totalLen, currLen;
char *line;
+#if (LIBSSH2_APINO >= 200706012030)
+ do {
+ sftp->sftp_handle =
+ libssh2_sftp_opendir(sftp->sftp_session, sftp->path);
+ if (!sftp->sftp_handle &&
+ (libssh2_session_last_errno(sftp->ssh_session) !=
+ LIBSSH2_ERROR_EAGAIN)) {
+ err = libssh2_sftp_last_error(sftp->sftp_session);
+ failf(conn->data, "Could not open directory for reading: %s",
+ sftp_libssh2_strerror(err));
+ return sftp_libssh2_error_to_CURLE(err);
+ }
+ } while (!sftp->sftp_handle);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
sftp->sftp_handle =
libssh2_sftp_opendir(sftp->sftp_session, sftp->path);
if (!sftp->sftp_handle) {
@@ -766,129 +931,148 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
sftp_libssh2_strerror(err));
return sftp_libssh2_error_to_CURLE(err);
}
-
- while ((len = libssh2_sftp_readdir(sftp->sftp_handle, filename,
- PATH_MAX, &attrs)) > 0) {
- filename[len] = '\0';
-
- if (data->set.ftp_list_only) {
- if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
- ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
- LIBSSH2_SFTP_S_IFDIR)) {
- infof(data, "%s\n", filename);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
+
+ do {
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((len = libssh2_sftp_readdir(sftp->sftp_handle, filename,
+ PATH_MAX, &attrs)) ==
+ LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
+ len = libssh2_sftp_readdir(sftp->sftp_handle, filename,
+ PATH_MAX, &attrs);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
+ if (len > 0) {
+ filename[len] = '\0';
+
+ if (data->set.ftp_list_only) {
+ if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
+ ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFDIR)) {
+ infof(data, "%s\n", filename);
+ }
}
- }
- else {
- totalLen = 80 + len;
- line = (char *)malloc(totalLen);
- if (!line)
- return CURLE_OUT_OF_MEMORY;
-
- if (!(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID))
- attrs.uid = attrs.gid =0;
-
- currLen = snprintf(line, totalLen, "---------- 1 %5d %5d",
- attrs.uid, attrs.gid);
+ else {
+ totalLen = 80 + len;
+ line = (char *)malloc(totalLen);
+ if (!line)
+ return CURLE_OUT_OF_MEMORY;
- if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
- if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
- LIBSSH2_SFTP_S_IFDIR) {
- line[0] = 'd';
- }
- else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
- LIBSSH2_SFTP_S_IFLNK) {
- line[0] = 'l';
- }
- else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
- LIBSSH2_SFTP_S_IFSOCK) {
- line[0] = 's';
- }
- else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
- LIBSSH2_SFTP_S_IFCHR) {
- line[0] = 'c';
- }
- else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
- LIBSSH2_SFTP_S_IFBLK) {
- line[0] = 'b';
- }
- if (attrs.permissions & LIBSSH2_SFTP_S_IRUSR) {
- line[1] = 'r';
- }
- if (attrs.permissions & LIBSSH2_SFTP_S_IWUSR) {
- line[2] = 'w';
- }
- if (attrs.permissions & LIBSSH2_SFTP_S_IXUSR) {
- line[3] = 'x';
- }
- if (attrs.permissions & LIBSSH2_SFTP_S_IRGRP) {
- line[4] = 'r';
- }
- if (attrs.permissions & LIBSSH2_SFTP_S_IWGRP) {
- line[5] = 'w';
+ if (!(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID))
+ attrs.uid = attrs.gid =0;
+
+ currLen = snprintf(line, totalLen, "---------- 1 %5d %5d",
+ attrs.uid, attrs.gid);
+
+ if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
+ if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFDIR) {
+ line[0] = 'd';
+ }
+ else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFLNK) {
+ line[0] = 'l';
+ }
+ else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFSOCK) {
+ line[0] = 's';
+ }
+ else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFCHR) {
+ line[0] = 'c';
+ }
+ else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFBLK) {
+ line[0] = 'b';
+ }
+ if (attrs.permissions & LIBSSH2_SFTP_S_IRUSR) {
+ line[1] = 'r';
+ }
+ if (attrs.permissions & LIBSSH2_SFTP_S_IWUSR) {
+ line[2] = 'w';
+ }
+ if (attrs.permissions & LIBSSH2_SFTP_S_IXUSR) {
+ line[3] = 'x';
+ }
+ if (attrs.permissions & LIBSSH2_SFTP_S_IRGRP) {
+ line[4] = 'r';
+ }
+ if (attrs.permissions & LIBSSH2_SFTP_S_IWGRP) {
+ line[5] = 'w';
+ }
+ if (attrs.permissions & LIBSSH2_SFTP_S_IXGRP) {
+ line[6] = 'x';
+ }
+ if (attrs.permissions & LIBSSH2_SFTP_S_IROTH) {
+ line[7] = 'r';
+ }
+ if (attrs.permissions & LIBSSH2_SFTP_S_IWOTH) {
+ line[8] = 'w';
+ }
+ if (attrs.permissions & LIBSSH2_SFTP_S_IXOTH) {
+ line[9] = 'x';
+ }
}
- if (attrs.permissions & LIBSSH2_SFTP_S_IXGRP) {
- line[6] = 'x';
+ if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
+ currLen += snprintf(line+currLen, totalLen-currLen, "%11lld",
+ attrs.filesize);
}
- if (attrs.permissions & LIBSSH2_SFTP_S_IROTH) {
- line[7] = 'r';
+ if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
+ static const char * const months[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ struct tm *nowParts;
+ time_t now, remoteTime;
+
+ now = time(NULL);
+ remoteTime = (time_t)attrs.mtime;
+ nowParts = localtime(&remoteTime);
+
+ if ((time_t)attrs.mtime > (now - (3600 * 24 * 180))) {
+ currLen += snprintf(line+currLen, totalLen-currLen,
+ " %s %2d %2d:%02d",
+ months[nowParts->tm_mon],
+ nowParts->tm_mday, nowParts->tm_hour,
+ nowParts->tm_min);
+ }
+ else {
+ currLen += snprintf(line+currLen, totalLen-currLen,
+ " %s %2d %5d", months[nowParts->tm_mon],
+ nowParts->tm_mday, 1900+nowParts->tm_year);
+ }
}
- if (attrs.permissions & LIBSSH2_SFTP_S_IWOTH) {
- line[8] = 'w';
- }
- if (attrs.permissions & LIBSSH2_SFTP_S_IXOTH) {
- line[9] = 'x';
- }
- }
- if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
- currLen += snprintf(line+currLen, totalLen-currLen, "%11lld",
- attrs.filesize);
- }
- if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
- static const char * const months[12] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- struct tm *nowParts;
- time_t now, remoteTime;
-
- now = time(NULL);
- remoteTime = (time_t)attrs.mtime;
- nowParts = localtime(&remoteTime);
-
- if ((time_t)attrs.mtime > (now - (3600 * 24 * 180))) {
- currLen += snprintf(line+currLen, totalLen-currLen,
- " %s %2d %2d:%02d", months[nowParts->tm_mon],
- nowParts->tm_mday, nowParts->tm_hour,
- nowParts->tm_min);
- }
- else {
- currLen += snprintf(line+currLen, totalLen-currLen,
- " %s %2d %5d", months[nowParts->tm_mon],
- nowParts->tm_mday, 1900+nowParts->tm_year);
+ currLen += snprintf(line+currLen, totalLen-currLen, " %s",
+ filename);
+ if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
+ ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFLNK)) {
+ char linkPath[PATH_MAX + 1];
+
+ snprintf(linkPath, PATH_MAX, "%s%s", sftp->path, filename);
+ len = libssh2_sftp_readlink(sftp->sftp_session, linkPath,
+ filename, PATH_MAX);
+ line = realloc(line, totalLen + 4 + len);
+ if (!line)
+ return CURLE_OUT_OF_MEMORY;
+
+ currLen += snprintf(line+currLen, totalLen-currLen, " -> %s",
+ filename);
}
- }
- currLen += snprintf(line+currLen, totalLen-currLen, " %s", filename);
- if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
- ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
- LIBSSH2_SFTP_S_IFLNK)) {
- char linkPath[PATH_MAX + 1];
-
- snprintf(linkPath, PATH_MAX, "%s%s", sftp->path, filename);
- len = libssh2_sftp_readlink(sftp->sftp_session, linkPath, filename,
- PATH_MAX);
- line = realloc(line, totalLen + 4 + len);
- if (!line)
- return CURLE_OUT_OF_MEMORY;
- currLen += snprintf(line+currLen, totalLen-currLen, " -> %s",
- filename);
+ currLen += snprintf(line+currLen, totalLen-currLen, "\n");
+ res = Curl_client_write(conn, CLIENTWRITE_BODY, line, 0);
+ free(line);
}
-
- currLen += snprintf(line+currLen, totalLen-currLen, "\n");
- res = Curl_client_write(conn, CLIENTWRITE_BODY, line, 0);
- free(line);
}
- }
+ else if (len <= 0) {
+ break;
+ }
+ } while (1);
+#if (LIBSSH2_APINO >= 200706012030)
+ while (libssh2_sftp_closedir(sftp->sftp_handle) == LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
libssh2_sftp_closedir(sftp->sftp_handle);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
sftp->sftp_handle = NULL;
/* no data to transfer */
@@ -898,6 +1082,22 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
/*
* Work on getting the specified file
*/
+#if (LIBSSH2_APINO >= 200706012030)
+ do {
+ sftp->sftp_handle =
+ libssh2_sftp_open(sftp->sftp_session, sftp->path, LIBSSH2_FXF_READ,
+ LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
+ LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
+ if (!sftp->sftp_handle &&
+ (libssh2_session_last_errno(sftp->ssh_session) !=
+ LIBSSH2_ERROR_EAGAIN)) {
+ err = libssh2_sftp_last_error(sftp->sftp_session);
+ failf(conn->data, "Could not open remote file for reading: %s",
+ sftp_libssh2_strerror(err));
+ return sftp_libssh2_error_to_CURLE(err);
+ }
+ } while (!sftp->sftp_handle);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
sftp->sftp_handle =
libssh2_sftp_open(sftp->sftp_session, sftp->path, LIBSSH2_FXF_READ,
LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
@@ -908,8 +1108,15 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
sftp_libssh2_strerror(err));
return sftp_libssh2_error_to_CURLE(err);
}
-
- if (libssh2_sftp_stat(sftp->sftp_session, sftp->path, &attrs)) {
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
+
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((rc = libssh2_sftp_stat(sftp->sftp_session, sftp->path, &attrs))
+ == LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
+ rc = libssh2_sftp_stat(sftp->sftp_session, sftp->path, &attrs);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
+ if (rc) {
/*
* libssh2_sftp_open() didn't return an error, so maybe the server
* just doesn't support stat()
@@ -935,19 +1142,31 @@ CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
bytecount, FALSE, NULL, -1, NULL);
#endif
while (res == CURLE_OK) {
+#if (LIBSSH2_APINO >= 200706012030)
+ ssize_t nread;
+
+ while ((nread = libssh2_sftp_read(data->reqdata.proto.ssh->sftp_handle,
+ buf, BUFSIZE-1)) == LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
size_t nread;
/* NOTE: most *read() functions return ssize_t but this returns size_t
- which normally is unsigned! */
+ which normally is unsigned! */
nread = libssh2_sftp_read(data->reqdata.proto.ssh->sftp_handle,
buf, BUFSIZE-1);
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
if (nread > 0)
buf[nread] = 0;
+#if (LIBSSH2_APINO >= 200706012030)
+ if (nread <= 0)
+ break;
+#else /* !(LIBSSH2_APINO >= 200706012030) */
/* this check can be changed to a <= 0 when nread is changed to a
- signed variable type */
+ signed variable type */
if ((nread == 0) || (nread == (size_t)~0))
break;
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
bytecount += nread;
@@ -980,6 +1199,7 @@ CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
{
struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
CURLcode rc = CURLE_OK;
+ int ret;
(void)premature; /* not used */
Curl_safefree(sftp->path);
@@ -989,9 +1209,17 @@ CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
sftp->homedir = NULL;
if (sftp->sftp_handle) {
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((ret = libssh2_sftp_close(sftp->sftp_handle)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (ret < 0) {
+ infof(conn->data, "Failed to close libssh2 file\n");
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
if (libssh2_sftp_close(sftp->sftp_handle) < 0) {
infof(conn->data, "Failed to close libssh2 file\n");
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
}
/* Before we shut down, see if there are any post-quote commands to send: */
@@ -1007,13 +1235,26 @@ CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
}
if (sftp->ssh_channel) {
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((ret = libssh2_channel_close(sftp->ssh_channel)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (ret < 0) {
+ infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
if (libssh2_channel_close(sftp->ssh_channel) < 0) {
infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
}
if (sftp->ssh_session) {
+#if (LIBSSH2_APINO >= 200706012030)
+ while (libssh2_session_disconnect(sftp->ssh_session, "Shutdown") ==
+ LIBSSH2_ERROR_EAGAIN);
+#else /* !(LIBSSH2_APINO >= 200706012030) */
libssh2_session_disconnect(sftp->ssh_session, "Shutdown");
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
libssh2_session_free(sftp->ssh_session);
sftp->ssh_session = NULL;
}
@@ -1034,7 +1275,7 @@ ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
but is changed to ssize_t in 0.15! */
-#ifdef LIBSSH2SFTP_EAGAIN
+#if defined(LIBSSH2SFTP_EAGAIN) && (LIBSSH2_APINO < 200706012030)
/* we prefer the non-blocking API but that didn't exist previously */
nwrite = (ssize_t)
libssh2_sftp_writenb(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
@@ -1190,6 +1431,7 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
long err;
struct SessionHandle *data = conn->data;
LIBSSH2_SFTP *sftp_session = data->reqdata.proto.ssh->sftp_session;
+ int ret;
while (item) {
if (item->data) {
@@ -1244,6 +1486,29 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
sftp_libssh2_strerror(err));
return CURLE_FTP_QUOTE_ERROR;
}
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((ret = libssh2_sftp_stat(sftp_session,
+ path2, &attrs)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (ret != 0) { /* get those attributes */
+ err = libssh2_sftp_last_error(sftp_session);
+ free(path1);
+ free(path2);
+ failf(data, "Attempt to get SFTP stats failed: %s",
+ sftp_libssh2_strerror(err));
+ return CURLE_FTP_QUOTE_ERROR;
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
+ if (libssh2_sftp_stat(sftp_session,
+ path2, &attrs) != 0) { /* get those attributes */
+ err = libssh2_sftp_last_error(sftp_session);
+ free(path1);
+ free(path2);
+ failf(data, "Attempt to get SFTP stats failed: %s",
+ sftp_libssh2_strerror(err));
+ return CURLE_FTP_QUOTE_ERROR;
+ }
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
/* Now set the new attributes... */
if (curl_strnequal(item->data, "chgrp", 5)) {
@@ -1275,6 +1540,18 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
}
/* Now send the completed structure... */
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((ret = libssh2_sftp_setstat(sftp_session, path2, &attrs)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (ret != 0) {
+ err = libssh2_sftp_last_error(sftp_session);
+ free(path1);
+ free(path2);
+ failf(data, "Attempt to set SFTP stats failed: %s",
+ sftp_libssh2_strerror(err));
+ return CURLE_FTP_QUOTE_ERROR;
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
if (libssh2_sftp_setstat(sftp_session, path2, &attrs) != 0) {
err = libssh2_sftp_last_error(sftp_session);
free(path1);
@@ -1283,6 +1560,7 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
sftp_libssh2_strerror(err));
return CURLE_FTP_QUOTE_ERROR;
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
}
else if (curl_strnequal(item->data, "ln ", 3) ||
curl_strnequal(item->data, "symlink ", 8)) {
@@ -1298,6 +1576,18 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
free(path1);
return err;
}
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((ret = libssh2_sftp_symlink(sftp_session, path1, path2)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (ret != 0) {
+ err = libssh2_sftp_last_error(sftp_session);
+ free(path1);
+ free(path2);
+ failf(data, "symlink command failed: %s",
+ sftp_libssh2_strerror(err));
+ return CURLE_FTP_QUOTE_ERROR;
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
if (libssh2_sftp_symlink(sftp_session, path1, path2) != 0) {
err = libssh2_sftp_last_error(sftp_session);
free(path1);
@@ -1306,8 +1596,19 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
sftp_libssh2_strerror(err));
return CURLE_FTP_QUOTE_ERROR;
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
}
else if (curl_strnequal(item->data, "mkdir ", 6)) { /* create dir */
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((ret = libssh2_sftp_mkdir(sftp_session, path1, 0744)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (ret != 0) {
+ err = libssh2_sftp_last_error(sftp_session);
+ free(path1);
+ failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
+ return CURLE_FTP_QUOTE_ERROR;
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
if (libssh2_sftp_mkdir(sftp_session, path1, 0744) != 0) {
err = libssh2_sftp_last_error(sftp_session);
free(path1);
@@ -1315,6 +1616,7 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
sftp_libssh2_strerror(err));
return CURLE_FTP_QUOTE_ERROR;
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
}
else if (curl_strnequal(item->data, "rename ", 7)) { /* rename file */
/* first param is the source path */
@@ -1328,6 +1630,17 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
free(path1);
return err;
}
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((ret = libssh2_sftp_rename(sftp_session, path1, path2)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (ret != 0) {
+ err = libssh2_sftp_last_error(sftp_session);
+ free(path1);
+ free(path2);
+ failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
+ return CURLE_FTP_QUOTE_ERROR;
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
if (libssh2_sftp_rename(sftp_session,
path1, path2) != 0) {
err = libssh2_sftp_last_error(sftp_session);
@@ -1337,8 +1650,19 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
sftp_libssh2_strerror(err));
return CURLE_FTP_QUOTE_ERROR;
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
}
else if (curl_strnequal(item->data, "rmdir ", 6)) { /* delete dir */
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((ret = libssh2_sftp_rmdir(sftp_session, path1)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (ret != 0) {
+ err = libssh2_sftp_last_error(sftp_session);
+ free(path1);
+ failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
+ return CURLE_FTP_QUOTE_ERROR;
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
if (libssh2_sftp_rmdir(sftp_session,
path1) != 0) {
err = libssh2_sftp_last_error(sftp_session);
@@ -1347,8 +1671,19 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
sftp_libssh2_strerror(err));
return CURLE_FTP_QUOTE_ERROR;
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
}
else if (curl_strnequal(item->data, "rm ", 3)) { /* delete file */
+#if (LIBSSH2_APINO >= 200706012030)
+ while ((ret = libssh2_sftp_unlink(sftp_session, path1)) ==
+ LIBSSH2_ERROR_EAGAIN);
+ if (ret != 0) {
+ err = libssh2_sftp_last_error(sftp_session);
+ free(path1);
+ failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
+ return CURLE_FTP_QUOTE_ERROR;
+ }
+#else /* !(LIBSSH2_APINO >= 200706012030) */
if (libssh2_sftp_unlink(sftp_session, path1) != 0) {
err = libssh2_sftp_last_error(sftp_session);
free(path1);
@@ -1356,6 +1691,7 @@ static CURLcode sftp_sendquote(struct connectdata *conn,
sftp_libssh2_strerror(err));
return CURLE_FTP_QUOTE_ERROR;
}
+#endif /* !(LIBSSH2_APINO >= 200706012030) */
}
if (path1)
@@ -1381,7 +1717,7 @@ ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
/* libssh2_sftp_read() returns size_t !*/
-#ifdef LIBSSH2SFTP_EAGAIN
+#if defined(LIBSSH2SFTP_EAGAIN) && (LIBSSH2_APINO < 200706012030)
/* we prefer the non-blocking API but that didn't exist previously */
nread = (ssize_t)
libssh2_sftp_readnb(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);