From 008b848dccafc18df79e0de9163b0bfab4f5392c Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 15 Dec 2008 23:04:51 +0000 Subject: [PATCH] - libssh2_sftp_last_error() was wrongly used at some places in libcurl which made libcurl sometimes not properly abort problematic SFTP transfers. --- CHANGES | 4 ++++ RELEASE-NOTES | 1 + lib/ssh.c | 44 ++++++++++++++++++++++++++++++++------------ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/CHANGES b/CHANGES index eaee3cb54..ba21b3f46 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,10 @@ Changelog +Daniel Stenberg (16 Dec 2008) +- libssh2_sftp_last_error() was wrongly used at some places in libcurl which + made libcurl sometimes not properly abort problematic SFTP transfers. + Daniel Stenberg (12 Dec 2008) - More work with Igor Novoseltsev to first fix the remaining stuff for removing easy handles from multi handles when the easy handle is/was within diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 96a3001ab..6183d4364 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -30,6 +30,7 @@ This release includes the following bugfixes: o dotted IPv6 addresses longer than 39 bytes failed o curl_easy_duphandle() doesn't try to duplicate the connection cache pointer o build failure on OS/400 when enabling IPv6 + o better detection of SFTP failures This release includes the following known bugs: diff --git a/lib/ssh.c b/lib/ssh.c index f826a4fa4..c97d0c7e8 100644 --- a/lib/ssh.c +++ b/lib/ssh.c @@ -778,6 +778,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* Return the error type */ err = libssh2_sftp_last_error(sshc->sftp_session); result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; DEBUGF(infof(data, "error = %d makes libcurl = %d\n", err, result)); state(conn, SSH_STOP); break; @@ -1238,16 +1239,22 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) flags, data->set.new_file_perms); if(!sshc->sftp_handle) { - if(libssh2_session_last_errno(sshc->ssh_session) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; + rc = libssh2_session_last_errno(sshc->ssh_session); + + if(LIBSSH2_ERROR_EAGAIN == rc) break; - } else { - err = libssh2_sftp_last_error(sshc->sftp_session); + if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc) + /* only when there was an SFTP protocol error can we extract + the sftp error! */ + err = libssh2_sftp_last_error(sshc->sftp_session); + else + err = -1; /* not an sftp error at all */ + if(sshc->secondCreateDirs) { state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = err>= LIBSSH2_FX_OK? + sftp_libssh2_error_to_CURLE(err):CURLE_SSH; failf(data, "Creating the dir/file failed: %s", sftp_libssh2_strerror(err)); break; @@ -1263,8 +1270,18 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) break; } state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = sftp_libssh2_error_to_CURLE(err); - failf(data, "Upload failed: %s", sftp_libssh2_strerror(err)); + sshc->actualcode = err>= LIBSSH2_FX_OK? + sftp_libssh2_error_to_CURLE(err):CURLE_SSH; + if(!sshc->actualcode) { + /* Sometimes, for some reason libssh2_sftp_last_error() returns zero + even though libssh2_sftp_open() failed previously! We need to + work around that! */ + sshc->actualcode = CURLE_SSH; + err=-1; + } + failf(data, "Upload failed: %s (%d/%d)", + err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error", + err, rc); break; } } @@ -1378,7 +1395,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) (sftp_err != LIBSSH2_FX_PERMISSION_DENIED)) { result = sftp_libssh2_error_to_CURLE(sftp_err); state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = result; + sshc->actualcode = result?result:CURLE_SSH; break; } } @@ -1403,7 +1420,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) failf(data, "Could not open directory for reading: %s", sftp_libssh2_strerror(err)); state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = sftp_libssh2_error_to_CURLE(err); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; break; } } @@ -1512,7 +1530,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) } else if(sshc->readdir_len <= 0) { err = libssh2_sftp_last_error(sshc->sftp_session); - sshc->actualcode = sftp_libssh2_error_to_CURLE(err); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; failf(data, "Could not open remote file for reading: %s :: %d", sftp_libssh2_strerror(err), libssh2_session_last_errno(sshc->ssh_session)); @@ -1621,7 +1640,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) failf(data, "Could not open remote file for reading: %s", sftp_libssh2_strerror(err)); state(conn, SSH_SFTP_CLOSE); - sshc->actualcode = sftp_libssh2_error_to_CURLE(err); + result = sftp_libssh2_error_to_CURLE(err); + sshc->actualcode = result?result:CURLE_SSH; break; } }