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.
This commit is contained in:
@@ -777,8 +777,6 @@ struct _LIBSSH2_SESSION
|
|||||||
#endif
|
#endif
|
||||||
long scpRecv_mtime;
|
long scpRecv_mtime;
|
||||||
long scpRecv_atime;
|
long scpRecv_atime;
|
||||||
char *scpRecv_err_msg;
|
|
||||||
long scpRecv_err_len;
|
|
||||||
LIBSSH2_CHANNEL *scpRecv_channel;
|
LIBSSH2_CHANNEL *scpRecv_channel;
|
||||||
|
|
||||||
/* State variables used in libssh2_scp_send_ex() */
|
/* State variables used in libssh2_scp_send_ex() */
|
||||||
@@ -787,8 +785,6 @@ struct _LIBSSH2_SESSION
|
|||||||
unsigned long scpSend_command_len;
|
unsigned long scpSend_command_len;
|
||||||
unsigned char scpSend_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
|
unsigned char scpSend_response[LIBSSH2_SCP_RESPONSE_BUFLEN];
|
||||||
unsigned long scpSend_response_len;
|
unsigned long scpSend_response_len;
|
||||||
char *scpSend_err_msg;
|
|
||||||
long scpSend_err_len;
|
|
||||||
LIBSSH2_CHANNEL *scpSend_channel;
|
LIBSSH2_CHANNEL *scpSend_channel;
|
||||||
|
|
||||||
/* Keepalive variables used by keepalive.c. */
|
/* Keepalive variables used by keepalive.c. */
|
||||||
|
83
src/scp.c
83
src/scp.c
@@ -402,38 +402,41 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb)
|
|||||||
session->scpRecv_response_len++;
|
session->scpRecv_response_len++;
|
||||||
|
|
||||||
if (session->scpRecv_response[0] != 'T') {
|
if (session->scpRecv_response[0] != 'T') {
|
||||||
/*
|
size_t err_len;
|
||||||
* Set this as the default error for here, if
|
char *err_msg;
|
||||||
* we are successful it will be replaced
|
|
||||||
*/
|
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
|
||||||
"Invalid data in SCP response, missing Time data");
|
|
||||||
|
|
||||||
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->
|
_libssh2_channel_packet_data_len(session->
|
||||||
scpRecv_channel, 0);
|
scpRecv_channel, 0);
|
||||||
session->scpRecv_err_msg =
|
err_msg = LIBSSH2_ALLOC(session, err_len + 1);
|
||||||
LIBSSH2_ALLOC(session, session->scpRecv_err_len + 1);
|
if (!err_msg) {
|
||||||
if (!session->scpRecv_err_msg) {
|
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"Failed to get memory ");
|
||||||
goto scp_recv_error;
|
goto scp_recv_error;
|
||||||
}
|
}
|
||||||
memset(session->scpRecv_err_msg, 0,
|
|
||||||
session->scpRecv_err_len + 1);
|
|
||||||
|
|
||||||
/* Read the remote error message */
|
/* Read the remote error message */
|
||||||
(void)_libssh2_channel_read(session->scpRecv_channel, 0,
|
(void)_libssh2_channel_read(session->scpRecv_channel, 0,
|
||||||
session->scpRecv_err_msg,
|
err_msg, err_len);
|
||||||
session->scpRecv_err_len);
|
|
||||||
/* If it failed for any reason, we ignore it anyway. */
|
/* 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,
|
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||||
"SCP protocol error");
|
"Failed to recv file");
|
||||||
|
|
||||||
/* TODO: for debugging purposes, the
|
LIBSSH2_FREE(session, err_msg);
|
||||||
session->scpRecv_err_msg should be displayed here
|
|
||||||
when available */
|
|
||||||
|
|
||||||
LIBSSH2_FREE(session, session->scpRecv_err_msg);
|
|
||||||
session->scpRecv_err_msg = NULL;
|
|
||||||
goto scp_recv_error;
|
goto scp_recv_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1001,38 +1004,30 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode,
|
|||||||
goto scp_send_empty_channel;
|
goto scp_send_empty_channel;
|
||||||
|
|
||||||
else if (session->scpSend_response[0] != 0) {
|
else if (session->scpSend_response[0] != 0) {
|
||||||
/*
|
size_t err_len;
|
||||||
* Set this as the default error for here, if
|
char *err_msg;
|
||||||
* we are successful it will be replaced
|
|
||||||
*/
|
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
|
||||||
"Invalid ACK response from remote");
|
|
||||||
|
|
||||||
session->scpSend_err_len =
|
err_len =
|
||||||
_libssh2_channel_packet_data_len(session->scpSend_channel, 0);
|
_libssh2_channel_packet_data_len(session->scpSend_channel, 0);
|
||||||
session->scpSend_err_msg =
|
err_msg = LIBSSH2_ALLOC(session, err_len + 1);
|
||||||
LIBSSH2_ALLOC(session, session->scpSend_err_len + 1);
|
if (!err_msg) {
|
||||||
if (!session->scpSend_err_msg) {
|
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"failed to get memory");
|
||||||
goto scp_send_error;
|
goto scp_send_error;
|
||||||
}
|
}
|
||||||
memset(session->scpSend_err_msg, 0, session->scpSend_err_len + 1);
|
|
||||||
|
|
||||||
/* Read the remote error message */
|
/* Read the remote error message */
|
||||||
rc = _libssh2_channel_read(session->scpSend_channel, 0,
|
rc = _libssh2_channel_read(session->scpSend_channel, 0,
|
||||||
session->scpSend_err_msg,
|
err_msg, err_len);
|
||||||
session->scpSend_err_len);
|
if (rc > 0) {
|
||||||
if (rc <= 0) {
|
err_msg[err_len]=0;
|
||||||
/*
|
_libssh2_debug(session, LIBSSH2_TRACE_SCP,
|
||||||
* Since we have alread started reading this packet, it is
|
"got %02x %s", session->scpSend_response[0],
|
||||||
* already in the systems so it can't return
|
err_msg);
|
||||||
* LIBSSH2_ERROR_EAGAIN
|
|
||||||
*/
|
|
||||||
LIBSSH2_FREE(session, session->scpSend_err_msg);
|
|
||||||
session->scpSend_err_msg = NULL;
|
|
||||||
}
|
}
|
||||||
else
|
LIBSSH2_FREE(session, err_msg);
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
_libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL,
|
||||||
"failed waiting for ACK");
|
"failed to send file");
|
||||||
goto scp_send_error;
|
goto scp_send_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -968,12 +968,6 @@ session_free(LIBSSH2_SESSION *session)
|
|||||||
if (session->scpSend_command) {
|
if (session->scpSend_command) {
|
||||||
LIBSSH2_FREE(session, 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 */
|
/* Cleanup all remaining packets */
|
||||||
while ((pkg = _libssh2_list_first(&session->packets))) {
|
while ((pkg = _libssh2_list_first(&session->packets))) {
|
||||||
|
Reference in New Issue
Block a user