diff --git a/include/libssh2_sftp.h b/include/libssh2_sftp.h index c553b89..e99a717 100644 --- a/include/libssh2_sftp.h +++ b/include/libssh2_sftp.h @@ -108,7 +108,7 @@ struct _LIBSSH2_SFTP_ATTRIBUTES { #define LIBSSH2_FXF_TRUNC 0x00000010 #define LIBSSH2_FXF_EXCL 0x00000020 -/* SFTP Status Codes */ +/* SFTP Status Codes (returned by libssh2_sftp_last_error() ) */ #define LIBSSH2_FX_OK 0 #define LIBSSH2_FX_EOF 1 #define LIBSSH2_FX_NO_SUCH_FILE 2 @@ -135,6 +135,7 @@ struct _LIBSSH2_SFTP_ATTRIBUTES { /* SFTP API */ LIBSSH2_API LIBSSH2_SFTP *libssh2_sftp_init(LIBSSH2_SESSION *session); LIBSSH2_API int libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp); +LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp); /* File / Directory Ops */ LIBSSH2_API LIBSSH2_SFTP_HANDLE *libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, char *filename, int filename_len, unsigned long flags, long mode, int open_type); diff --git a/src/sftp.c b/src/sftp.c index cad530d..3e99cb3 100644 --- a/src/sftp.c +++ b/src/sftp.c @@ -82,6 +82,8 @@ struct _LIBSSH2_SFTP { LIBSSH2_PACKET_BRIGADE packets; LIBSSH2_SFTP_HANDLE *handles; + + unsigned long errno; }; #define LIBSSH2_SFTP_HANDLE_FILE 0 @@ -540,6 +542,7 @@ LIBSSH2_API LIBSSH2_SFTP_HANDLE *libssh2_sftp_open_ex(LIBSSH2_SFTP *sftp, char * if (data[0] == SSH_FXP_STATUS) { libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Failed opening remote file", 0); + sftp->errno = libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); return NULL; } @@ -624,6 +627,8 @@ LIBSSH2_API size_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer, switch (data[0]) { case SSH_FXP_STATUS: + sftp->errno = libssh2_ntohu32(data + 5); + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); LIBSSH2_FREE(session, data); return -1; case SSH_FXP_DATA: @@ -710,10 +715,17 @@ LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, } if (data[0] == SSH_FXP_STATUS) { - int retcode = (LIBSSH2_FX_EOF == libssh2_ntohu32(data + 5)) ? 0 : -1; + int retcode; + retcode = libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - return retcode; + if (retcode == LIBSSH2_FX_EOF) { + return 0; + } else { + sftp->errno = retcode; + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); + return -1; + } } num_names = libssh2_ntohu32(data + 5); @@ -796,6 +808,8 @@ LIBSSH2_API size_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *b handle->u.file.offset += count; return count; } + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); + sftp->errno = retcode; return -1; } @@ -848,7 +862,13 @@ LIBSSH2_API int libssh2_sftp_fstat_ex(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_ retcode = libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - return (retcode == LIBSSH2_FX_OK) ? 0 : -1; + if (retcode == LIBSSH2_FX_OK) { + return 0; + } else { + sftp->errno = retcode; + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); + return -1; + } } libssh2_sftp_bin2attr(attrs, data + 5); @@ -918,6 +938,8 @@ LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle) LIBSSH2_FREE(session, data); if (retcode != LIBSSH2_FX_OK) { + sftp->errno = retcode; + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); return -1; } @@ -981,7 +1003,13 @@ LIBSSH2_API int libssh2_sftp_unlink_ex(LIBSSH2_SFTP *sftp, char *filename, int f retcode = libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - return (retcode == LIBSSH2_FX_OK) ? 0 : -1; + if (retcode == LIBSSH2_FX_OK) { + return 0; + } else { + sftp->errno = retcode; + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); + return -1; + } } /* }}} */ @@ -1027,19 +1055,27 @@ LIBSSH2_API int libssh2_sftp_rename_ex(LIBSSH2_SFTP *sftp, char *source_filenam return -1; } - switch (libssh2_ntohu32(data + 5)) { + retcode = libssh2_ntohu32(data + 5); + LIBSSH2_FREE(session, data); + + switch (retcode) { case LIBSSH2_FX_OK: retcode = 0; - LIBSSH2_FREE(session, data); break; case LIBSSH2_FX_FILE_ALREADY_EXISTS: libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "File already exists and SSH_FXP_RENAME_OVERWRITE not specified", 0); + sftp->errno = retcode; retcode = -1; break; case LIBSSH2_FX_OP_UNSUPPORTED: libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "Operation Not Supported", 0); + sftp->errno = retcode; retcode = -1; break; + default: + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); + sftp->errno = retcode; + retcode = -1; } return retcode; @@ -1089,7 +1125,13 @@ LIBSSH2_API int libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, char *path, int path_l retcode = libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - return (retcode == LIBSSH2_FX_OK) ? 0 : -1; + if (retcode == LIBSSH2_FX_OK) { + return 0; + } else { + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); + sftp->errno = retcode; + return -1; + } } /* }}} */ @@ -1132,7 +1174,13 @@ LIBSSH2_API int libssh2_sftp_rmdir_ex(LIBSSH2_SFTP *sftp, char *path, int path_l retcode = libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - return (retcode == LIBSSH2_FX_OK) ? 0 : -1; + if (retcode == LIBSSH2_FX_OK) { + return 0; + } else { + sftp->errno = retcode; + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); + return -1; + } } /* }}} */ @@ -1192,7 +1240,13 @@ LIBSSH2_API int libssh2_sftp_stat_ex(LIBSSH2_SFTP *sftp, char *path, int path_le retcode = libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - return (retcode == LIBSSH2_FX_OK) ? 0 : 1; + if (retcode == LIBSSH2_FX_OK) { + return 0; + } else { + sftp->errno = retcode; + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); + return -1; + } } memset(attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES)); @@ -1260,7 +1314,13 @@ LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, in retcode = libssh2_ntohu32(data + 5); LIBSSH2_FREE(session, data); - return (retcode == LIBSSH2_FX_OK) ? 0 : 1; + if (retcode == LIBSSH2_FX_OK) { + return 0; + } else { + sftp->errno = retcode; + libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); + return -1; + } } if (libssh2_ntohu32(data + 5) < 1) { @@ -1278,3 +1338,12 @@ LIBSSH2_API int libssh2_sftp_symlink_ex(LIBSSH2_SFTP *sftp, const char *path, in return link_len; } /* }}} */ + +/* {{{ libssh2_sftp_last_error + * Returns the last error code reported by SFTP + */ +LIBSSH2_API unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp) +{ + return sftp->errno; +} +/* }}} */