From ae6144f596bce5b792ff818df3e6642ff2ff5e60 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 23 Jan 2019 18:22:56 -0800 Subject: [PATCH] 1. Add the default path parameter to the wolfsftp client. 2. Split the error check on the Windows file write into two checks. 3. Check the success of closing the local file in Windows. 4. Rearrange the Get state machine to attempt to close the remote file first then the local file. The local file close is always attempted. --- examples/sftpclient/sftpclient.c | 16 ++++++++++- src/internal.c | 3 ++ src/wolfsftp.c | 47 ++++++++++++++++++++++---------- wolfssh/error.h | 3 +- 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index 1f2629f..4beb3f5 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -269,6 +269,7 @@ static void ShowUsage(void) printf(" -p port to connect on, default %d\n", wolfSshPort); printf(" -u username to authenticate as (REQUIRED)\n"); printf(" -P password for username, prompted if omitted\n"); + printf(" -d set the default local path\n"); printf(" -N use non blocking sockets\n"); ShowCommands(); @@ -885,14 +886,19 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) char* host = (char*)wolfSshIp; const char* username = NULL; const char* password = NULL; + const char* defaultSftpPath = NULL; byte nonBlock = 0; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; ((func_args*)args)->return_code = 0; - while ((ch = mygetopt(argc, argv, "?h:p:u:P:N")) != -1) { + while ((ch = mygetopt(argc, argv, "?d:h:p:u:P:N")) != -1) { switch (ch) { + case 'd': + defaultSftpPath = myoptarg; + break; + case 'h': host = myoptarg; break; @@ -949,6 +955,14 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) if (ssh == NULL) err_sys("Couldn't create wolfSSH session."); + if (defaultSftpPath != NULL) { + if (wolfSSH_SFTP_SetDefaultPath(ssh, defaultSftpPath) + != WS_SUCCESS) { + fprintf(stderr, "Couldn't store default sftp path.\n"); + exit(EXIT_FAILURE); + } + } + if (password != NULL) wolfSSH_SetUserAuthCtx(ssh, (void*)password); diff --git a/src/internal.c b/src/internal.c index be16851..7f52426 100644 --- a/src/internal.c +++ b/src/internal.c @@ -263,6 +263,9 @@ const char* GetErrorString(int err) case WS_SIZE_ONLY: return "Only getting the size of buffer needed"; + case WS_CLOSE_FILE_E: + return "Unable to close local file"; + default: return "Unknown error code"; } diff --git a/src/wolfsftp.c b/src/wolfsftp.c index 571dd05..7b774af 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -6785,7 +6785,7 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from, if (state->gOfst > 0) desiredAccess |= FILE_APPEND_DATA; state->fileHandle = CreateFileA(to, desiredAccess, - 0, NULL, CREATE_NEW, + 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } if (resume) { @@ -6836,8 +6836,18 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from, { DWORD bytesWritten = 0; if (WriteFile(state->fileHandle, state->r, sz, - &bytesWritten, &state->offset) == 0 || - (DWORD)sz != bytesWritten) { + &bytesWritten, &state->offset) == 0) { + WLOG(WS_LOG_SFTP, "Error writing to file"); + ssh->error = WS_BAD_FILE_E; + ret = WS_FATAL_ERROR; + state->state = STATE_GET_CLEANUP; + break; /* either at end of file or error */ + } + if ((DWORD)sz != bytesWritten) { + WLOG(WS_LOG_SFTP, "Error writing to file"); + ssh->error = WS_MATCH_KEX_ALGO_E; + ret = WS_FATAL_ERROR; + state->state = STATE_GET_CLEANUP; break; /* either at end of file or error */ } } @@ -6859,16 +6869,6 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from, wolfSSH_SFTP_SaveOfst(ssh, from, to, state->gOfst); } ssh->sftpInt = 0; - state->state = STATE_GET_CLOSE_LOCAL; - FALL_THROUGH; - - case STATE_GET_CLOSE_LOCAL: - WLOG(WS_LOG_SFTP, "SFTP GET STATE: CLOSE LOCAL"); - #ifndef USE_WINDOWS_API - WFCLOSE(state->fl); - #else /* USE_WINDOWS_API */ - CloseHandle(state->fileHandle); - #endif /* USE_WINDOWS_API */ state->state = STATE_GET_CLOSE_REMOTE; FALL_THROUGH; @@ -6877,9 +6877,26 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from, ret = wolfSSH_SFTP_Close(ssh, state->handle, state->handleSz); if (ret != WS_SUCCESS) { - WLOG(WS_LOG_SFTP, "Error closing handle"); - return WS_FATAL_ERROR; + if (ssh->error == WS_WANT_READ || + ssh->error == WS_WANT_WRITE) { + return WS_FATAL_ERROR; + } + WLOG(WS_LOG_SFTP, "Error closing remote handle"); } + state->state = STATE_GET_CLOSE_LOCAL; + FALL_THROUGH; + + case STATE_GET_CLOSE_LOCAL: + WLOG(WS_LOG_SFTP, "SFTP GET STATE: CLOSE LOCAL"); + #ifndef USE_WINDOWS_API + WFCLOSE(state->fl); + #else /* USE_WINDOWS_API */ + if (CloseHandle(state->fileHandle) == 0) { + WLOG(WS_LOG_SFTP, "Error closing file."); + ret = WS_FATAL_ERROR; + ssh->error = WS_CLOSE_FILE_E; + } + #endif /* USE_WINDOWS_API */ state->state = STATE_GET_CLEANUP; FALL_THROUGH; diff --git a/wolfssh/error.h b/wolfssh/error.h index 525f6be..bd0fb3d 100644 --- a/wolfssh/error.h +++ b/wolfssh/error.h @@ -102,8 +102,9 @@ enum WS_ErrorCodes { WS_SFTP_STATUS_NOT_OK = -62, /* SFTP Status not OK */ WS_SFTP_FILE_DNE = -63, /* SFTP File Does Not Exist */ WS_SIZE_ONLY = -64, /* Only getting the size of buffer needed */ + WS_CLOSE_FILE_E = -65, /* Unable to close local file */ - WS_LAST_E = -64 /* Update this to indicate last error */ + WS_LAST_E = -65 /* Update this to indicate last error */ };