mirror of
				https://github.com/libssh2/libssh2.git
				synced 2025-11-03 22:13:11 +03:00 
			
		
		
		
	Gavrie Philipson sumitted a patch to get the actual text of the error
on scp upload.
This commit is contained in:
		@@ -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;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user