From 1c3e1c4d2513252ad4e60d83d37c1a0cba2b098a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 10 Nov 2010 17:17:32 +0100 Subject: [PATCH] SCP: clean up failure treatment When SCP send or recv fails, it gets a special message from the server with a warning or error message included. We have no current API to expose that message but the foundation is there. Removed unnecessary use of session struct fields. --- src/libssh2_priv.h | 4 --- src/scp.c | 85 ++++++++++++++++++++++------------------------ src/session.c | 6 ---- 3 files changed, 40 insertions(+), 55 deletions(-) diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 23c5ff5..ad841f8 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -777,8 +777,6 @@ struct _LIBSSH2_SESSION #endif long scpRecv_mtime; long scpRecv_atime; - char *scpRecv_err_msg; - long scpRecv_err_len; LIBSSH2_CHANNEL *scpRecv_channel; /* State variables used in libssh2_scp_send_ex() */ @@ -787,8 +785,6 @@ struct _LIBSSH2_SESSION unsigned long scpSend_command_len; unsigned char scpSend_response[LIBSSH2_SCP_RESPONSE_BUFLEN]; unsigned long scpSend_response_len; - char *scpSend_err_msg; - long scpSend_err_len; LIBSSH2_CHANNEL *scpSend_channel; /* Keepalive variables used by keepalive.c. */ diff --git a/src/scp.c b/src/scp.c index 1e60024..5e3b056 100644 --- a/src/scp.c +++ b/src/scp.c @@ -402,38 +402,41 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb) session->scpRecv_response_len++; if (session->scpRecv_response[0] != 'T') { - /* - * Set this as the default error for here, if - * we are successful it will be replaced - */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid data in SCP response, missing Time data"); + size_t err_len; + char *err_msg; - session->scpRecv_err_len = + /* there can be + 01 for warnings + 02 for errors + + The following string MUST be newline terminated + */ + err_len = _libssh2_channel_packet_data_len(session-> scpRecv_channel, 0); - session->scpRecv_err_msg = - LIBSSH2_ALLOC(session, session->scpRecv_err_len + 1); - if (!session->scpRecv_err_msg) { + err_msg = LIBSSH2_ALLOC(session, err_len + 1); + if (!err_msg) { + _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "Failed to get memory "); goto scp_recv_error; } - memset(session->scpRecv_err_msg, 0, - session->scpRecv_err_len + 1); /* Read the remote error message */ (void)_libssh2_channel_read(session->scpRecv_channel, 0, - session->scpRecv_err_msg, - session->scpRecv_err_len); + err_msg, err_len); /* If it failed for any reason, we ignore it anyway. */ + + /* zero terminate the error */ + err_msg[err_len]=0; + + _libssh2_debug(session, LIBSSH2_TRACE_SCP, + "got %02x %s", session->scpRecv_response[0], + err_msg); + _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "SCP protocol error"); + "Failed to recv file"); - /* TODO: for debugging purposes, the - session->scpRecv_err_msg should be displayed here - when available */ - - LIBSSH2_FREE(session, session->scpRecv_err_msg); - session->scpRecv_err_msg = NULL; + LIBSSH2_FREE(session, err_msg); goto scp_recv_error; } @@ -1001,38 +1004,30 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, goto scp_send_empty_channel; else if (session->scpSend_response[0] != 0) { - /* - * Set this as the default error for here, if - * we are successful it will be replaced - */ - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "Invalid ACK response from remote"); + size_t err_len; + char *err_msg; - session->scpSend_err_len = + err_len = _libssh2_channel_packet_data_len(session->scpSend_channel, 0); - session->scpSend_err_msg = - LIBSSH2_ALLOC(session, session->scpSend_err_len + 1); - if (!session->scpSend_err_msg) { + err_msg = LIBSSH2_ALLOC(session, err_len + 1); + if (!err_msg) { + _libssh2_error(session, LIBSSH2_ERROR_ALLOC, + "failed to get memory"); goto scp_send_error; } - memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1); /* Read the remote error message */ rc = _libssh2_channel_read(session->scpSend_channel, 0, - session->scpSend_err_msg, - session->scpSend_err_len); - if (rc <= 0) { - /* - * Since we have alread started reading this packet, it is - * already in the systems so it can't return - * LIBSSH2_ERROR_EAGAIN - */ - LIBSSH2_FREE(session, session->scpSend_err_msg); - session->scpSend_err_msg = NULL; + err_msg, err_len); + if (rc > 0) { + err_msg[err_len]=0; + _libssh2_debug(session, LIBSSH2_TRACE_SCP, + "got %02x %s", session->scpSend_response[0], + err_msg); } - else - _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, - "failed waiting for ACK"); + LIBSSH2_FREE(session, err_msg); + _libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, + "failed to send file"); goto scp_send_error; } } diff --git a/src/session.c b/src/session.c index e8798f5..90dbb81 100644 --- a/src/session.c +++ b/src/session.c @@ -968,12 +968,6 @@ session_free(LIBSSH2_SESSION *session) if (session->scpSend_command) { LIBSSH2_FREE(session, session->scpSend_command); } - if (session->scpRecv_err_msg) { - LIBSSH2_FREE(session, session->scpRecv_err_msg); - } - if (session->scpSend_err_msg) { - LIBSSH2_FREE(session, session->scpSend_err_msg); - } /* Cleanup all remaining packets */ while ((pkg = _libssh2_list_first(&session->packets))) {