Gavrie Philipson sumitted a patch to get the actual text of the error
on scp upload.
Этот коммит содержится в:
родитель
a9fc3bdb4e
Коммит
530e57d4ac
@ -1,3 +1,7 @@
|
|||||||
|
2007-07-05 James Housley <jim@thehousleys.net>
|
||||||
|
* Gavrie Philipson sumitted a patch to get the actual text
|
||||||
|
of the error on scp upload.
|
||||||
|
|
||||||
2007-06-23 James Housley <jim@thehousleys.net>
|
2007-06-23 James Housley <jim@thehousleys.net>
|
||||||
* Eberhard Mattes submitted a patch "According to RFC 4251,
|
* Eberhard Mattes submitted a patch "According to RFC 4251,
|
||||||
a boolean value of true is encoded as 1, not as 0xff". Servers
|
a boolean value of true is encoded as 1, not as 0xff". Servers
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: scp_write_nonblock.c,v 1.2 2007/06/08 13:33:08 jehousley Exp $
|
* $Id: scp_write_nonblock.c,v 1.3 2007/07/05 11:08:17 jehousley Exp $
|
||||||
*
|
*
|
||||||
* Sample showing how to do a simple SCP transfer.
|
* Sample showing how to do a simple SCP transfer.
|
||||||
*/
|
*/
|
||||||
@ -165,7 +165,10 @@ int main(int argc, char *argv[])
|
|||||||
channel = libssh2_scp_send(session, scppath, 0x1FF & fileinfo.st_mode, (unsigned long)fileinfo.st_size);
|
channel = libssh2_scp_send(session, scppath, 0x1FF & fileinfo.st_mode, (unsigned long)fileinfo.st_size);
|
||||||
|
|
||||||
if ((!channel) && (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) {
|
if ((!channel) && (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN)) {
|
||||||
fprintf(stderr, "Unable to open a session\n");
|
char *err_msg;
|
||||||
|
|
||||||
|
libssh2_session_last_error(session, &err_msg, NULL, 0);
|
||||||
|
fprintf(stderr, "%s\n", err_msg);
|
||||||
goto shutdown;
|
goto shutdown;
|
||||||
}
|
}
|
||||||
} while (!channel);
|
} while (!channel);
|
||||||
|
@ -1172,7 +1172,7 @@ libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel, int ignore_mode)
|
|||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* {{{ _libssh2_channel_read_ex
|
* {{{ libssh2_channel_read_ex
|
||||||
* Read data from a channel blocking or non-blocking depending on set state
|
* Read data from a channel blocking or non-blocking depending on set state
|
||||||
*
|
*
|
||||||
* When this is done non-blocking, it is important to not return 0 until the
|
* When this is done non-blocking, it is important to not return 0 until the
|
||||||
@ -1329,6 +1329,52 @@ channel_read_ex_point1:
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* {{{ libssh2_channel_packet_data_len
|
||||||
|
* Return the size of the data block of the current packet, or 0 if there
|
||||||
|
* isn't a packet.
|
||||||
|
*/
|
||||||
|
unsigned long
|
||||||
|
libssh2_channel_packet_data_len(LIBSSH2_CHANNEL *channel, int stream_id)
|
||||||
|
{
|
||||||
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
|
LIBSSH2_PACKET *read_packet;
|
||||||
|
uint32_t read_local_id;
|
||||||
|
|
||||||
|
if ((read_packet = session->packets.head) == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (read_packet) {
|
||||||
|
read_local_id = libssh2_ntohu32(read_packet->data + 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Either we asked for a specific extended data stream
|
||||||
|
* (and data was available),
|
||||||
|
* or the standard stream (and data was available),
|
||||||
|
* or the standard stream with extended_data_merge
|
||||||
|
* enabled and data was available
|
||||||
|
*/
|
||||||
|
if ((stream_id && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) &&
|
||||||
|
(channel->local.id == read_local_id) &&
|
||||||
|
(stream_id == (int)libssh2_ntohu32(read_packet->data + 5))) ||
|
||||||
|
|
||||||
|
(!stream_id && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA) &&
|
||||||
|
(channel->local.id == read_local_id)) ||
|
||||||
|
|
||||||
|
(!stream_id && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) &&
|
||||||
|
(channel->local.id == read_local_id) &&
|
||||||
|
(channel->remote.extended_data_ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
|
||||||
|
|
||||||
|
return (read_packet->data_len - read_packet->data_head);
|
||||||
|
}
|
||||||
|
read_packet = read_packet->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ libssh2_channel_write_ex
|
/* {{{ libssh2_channel_write_ex
|
||||||
* Send data to a channel
|
* Send data to a channel
|
||||||
*/
|
*/
|
||||||
|
@ -798,6 +798,8 @@ 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1041,6 +1043,7 @@ int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, size_t dat
|
|||||||
int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange, key_exchange_state_t *state);
|
int libssh2_kex_exchange(LIBSSH2_SESSION *session, int reexchange, key_exchange_state_t *state);
|
||||||
unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session);
|
unsigned long libssh2_channel_nextid(LIBSSH2_SESSION *session);
|
||||||
LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id);
|
LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long channel_id);
|
||||||
|
unsigned long libssh2_channel_packet_data_len(LIBSSH2_CHANNEL *channel, int stream_id);
|
||||||
|
|
||||||
/* this is the lib-internal set blocking function */
|
/* this is the lib-internal set blocking function */
|
||||||
int _libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking);
|
int _libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking);
|
||||||
|
61
src/scp.c
61
src/scp.c
@ -419,6 +419,15 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
|
|||||||
unsigned const char *base;
|
unsigned const char *base;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* =============================== NOTE ===============================
|
||||||
|
* I know this is very ugly and not a really good use of "goto", but
|
||||||
|
* this case statement would be even uglier to do it any other way
|
||||||
|
*/
|
||||||
|
if (session->scpSend_state == libssh2_NB_state_jump1) {
|
||||||
|
goto scp_read_ex_point1;
|
||||||
|
}
|
||||||
|
|
||||||
if (session->scpSend_state == libssh2_NB_state_idle) {
|
if (session->scpSend_state == libssh2_NB_state_idle) {
|
||||||
session->scpSend_command_len = path_len + sizeof("scp -t ");
|
session->scpSend_command_len = path_len + sizeof("scp -t ");
|
||||||
|
|
||||||
@ -577,15 +586,49 @@ libssh2_scp_send_ex(LIBSSH2_SESSION *session, const char *path, int mode, size_t
|
|||||||
session->scpSend_state = libssh2_NB_state_sent6;
|
session->scpSend_state = libssh2_NB_state_sent6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for ACK */
|
if (session->scpSend_state == libssh2_NB_state_sent6) {
|
||||||
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, (char *)session->scpSend_response, 1);
|
/* Wait for ACK */
|
||||||
if (rc == PACKET_EAGAIN) {
|
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, (char *)session->scpSend_response, 1);
|
||||||
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response", 0);
|
if (rc == PACKET_EAGAIN) {
|
||||||
return NULL;
|
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response", 0);
|
||||||
}
|
return NULL;
|
||||||
else if ((rc <= 0) || (session->scpSend_response[0] != 0)) {
|
}
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote", 0);
|
else if (rc <= 0) {
|
||||||
goto scp_send_error;
|
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, "Invalid ACK response from remote", 0);
|
||||||
|
goto scp_send_error;
|
||||||
|
}
|
||||||
|
else if (session->scpSend_response[0] != 0) {
|
||||||
|
session->scpSend_state = libssh2_NB_state_jump1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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", 0);
|
||||||
|
|
||||||
|
session->scpSend_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) {
|
||||||
|
goto scp_send_error;
|
||||||
|
}
|
||||||
|
memset(session->scpSend_err_msg, 0, session->scpSend_err_len+1);
|
||||||
|
|
||||||
|
/* Read the remote error message */
|
||||||
|
scp_read_ex_point1:
|
||||||
|
rc = libssh2_channel_read_ex(session->scpSend_channel, 0, session->scpSend_err_msg, session->scpSend_err_len);
|
||||||
|
if (rc == PACKET_EAGAIN) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting for response", 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (rc <= 0) {
|
||||||
|
LIBSSH2_FREE(session, session->scpSend_err_msg);
|
||||||
|
session->scpSend_err_msg = NULL;
|
||||||
|
goto scp_send_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_SCP_PROTOCOL, session->scpSend_err_msg, 1);
|
||||||
|
goto scp_send_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
session->scpSend_state = libssh2_NB_state_idle;
|
session->scpSend_state = libssh2_NB_state_idle;
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user