removed some more libssh2_ prefixes from private functions

Made the libssh2_sftp_open_ex() deal with servers that first responds with
STATUS OK and then sends the actual HANDLE. It seems openssh does this at
times and it screwed things up. To me it seems like a spec violation...
This commit is contained in:
Daniel Stenberg 2008-12-16 15:35:33 +00:00
parent 197a26ef8c
commit 2535c5c2ee

View File

@ -82,18 +82,18 @@
/* S_IFDIR */
#define LIBSSH2_SFTP_ATTR_PFILETYPE_DIR 0040000
/* {{{ libssh2_sftp_packet_add
/* {{{ sftp_packet_add
* Add a packet to the SFTP packet brigade
*/
static int
libssh2_sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
unsigned long data_len)
sftp_packet_add(LIBSSH2_SFTP * sftp, unsigned char *data,
unsigned long data_len)
{
LIBSSH2_SESSION *session = sftp->channel->session;
LIBSSH2_PACKET *packet;
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d",
(int) data[0]);
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Received packet %d (len %d)",
(int) data[0], data_len);
packet = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
@ -139,16 +139,24 @@ sftp_packet_read(LIBSSH2_SFTP * sftp)
/* If there was a previous partial, start using it */
if (sftp->partial_packet) {
packet = sftp->partial_packet;
packet_len = sftp->partial_len;
packet_received = sftp->partial_received;
sftp->partial_packet = NULL;
_libssh2_debug(session, LIBSSH2_DBG_SFTP,
"partial read cont, len: %lu", packet_len);
}
else {
rc = libssh2_channel_read_ex(channel, 0, (char *) buffer, 4);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (4 != rc) {
}
else if (4 != rc) {
/* TODO: this is stupid since we can in fact get 1-3 bytes in a
legitimate working case as well if the connection happens to be
super slow or something */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for FXP packet", 0);
return -1;
@ -201,7 +209,7 @@ sftp_packet_read(LIBSSH2_SFTP * sftp)
packet_received += bytes_received;
}
if (libssh2_sftp_packet_add(sftp, packet, packet_len)) {
if (sftp_packet_add(sftp, packet, packet_len)) {
LIBSSH2_FREE(session, packet);
return -1;
}
@ -211,13 +219,13 @@ sftp_packet_read(LIBSSH2_SFTP * sftp)
/* }}} */
/* {{{ libssh2_sftp_packet_ask
/* {{{ sftp_packet_ask
* A la libssh2_packet_ask()
*/
static int
libssh2_sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data,
unsigned long *data_len, int poll_channel)
sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data,
unsigned long *data_len, int poll_channel)
{
LIBSSH2_SESSION *session = sftp->channel->session;
LIBSSH2_PACKET *packet = sftp->packets.head;
@ -271,13 +279,13 @@ libssh2_sftp_packet_ask(LIBSSH2_SFTP * sftp, unsigned char packet_type,
/* }}} */
/* {{{ libssh2_sftp_packet_require
/* {{{ sftp_packet_require
* A la libssh2_packet_require
*/
static int
libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data,
unsigned long *data_len)
sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
unsigned long request_id, unsigned char **data,
unsigned long *data_len)
{
LIBSSH2_SESSION *session = sftp->channel->session;
int ret;
@ -285,8 +293,8 @@ libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requiring %d packet",
(int) packet_type);
if (libssh2_sftp_packet_ask
(sftp, packet_type, request_id, data, data_len, 0) == 0) {
if (sftp_packet_ask(sftp, packet_type, request_id, data,
data_len, 0) == 0) {
/* The right packet was available in the packet brigade */
return 0;
}
@ -301,8 +309,8 @@ libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
if (packet_type == ret) {
/* Be lazy, let packet_ask pull it out of the brigade */
return libssh2_sftp_packet_ask(sftp, packet_type, request_id, data,
data_len, 0);
return sftp_packet_ask(sftp, packet_type, request_id, data,
data_len, 0);
}
}
@ -313,7 +321,7 @@ libssh2_sftp_packet_require(LIBSSH2_SFTP * sftp, unsigned char packet_type,
/* }}} */
/* {{{ sftp_packet_requirev
* Requie one of N possible reponses
* Require one of N possible reponses
*/
static int
sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
@ -331,8 +339,8 @@ sftp_packet_requirev(LIBSSH2_SFTP * sftp, int num_valid_responses,
while (sftp->channel->session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
for(i = 0; i < num_valid_responses; i++) {
if (libssh2_sftp_packet_ask(sftp, valid_responses[i], request_id,
data, data_len, 0) == 0) {
if (sftp_packet_ask(sftp, valid_responses[i], request_id,
data, data_len, 0) == 0) {
/*
* Set to zero before all returns to say
* the timeout is not active
@ -633,8 +641,8 @@ libssh2_sftp_init(LIBSSH2_SESSION * session)
}
/* For initiallization we are requiring blocking, probably reasonable */
rc = libssh2_sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION,
0, &data, &data_len);
rc = sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION,
0, &data, &data_len);
if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for response from SFTP subsystem",
@ -788,7 +796,8 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
int rc;
if (sftp->open_state == libssh2_NB_state_idle) {
/* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) + flags(4) */
/* packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) +
flags(4) */
sftp->open_packet_len = filename_len + 13 +
((open_type ==
LIBSSH2_SFTP_OPENFILE) ? (4 +
@ -797,7 +806,8 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
s = sftp->open_packet = LIBSSH2_ALLOC(session, sftp->open_packet_len);
if (!sftp->open_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_OPEN or FXP_OPENDIR packet",
"Unable to allocate memory for FXP_OPEN or "
"FXP_OPENDIR packet",
0);
return NULL;
}
@ -840,7 +850,11 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
"Would block sending FXP_OPEN or FXP_OPENDIR command",
0);
return NULL;
} else if (sftp->open_packet_len != rc) {
}
else if (sftp->open_packet_len != rc) {
/* TODO: partial writes should be fine too and is not a sign of
an error when in non-blocking mode! */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_OPEN or FXP_OPENDIR command", 0);
LIBSSH2_FREE(session, sftp->open_packet);
@ -862,7 +876,8 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block waiting for status message", 0);
return NULL;
} else if (rc) {
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
sftp->open_state = libssh2_NB_state_idle;
@ -872,12 +887,38 @@ libssh2_sftp_open_ex(LIBSSH2_SFTP * sftp, const char *filename,
sftp->open_state = libssh2_NB_state_idle;
/* OPEN can basically get STATUS or HANDLE back, where HANDLE implies a
fine response while STATUS means error. It seems though that at times
we get an SSH_FX_OK back in a STATUS, followed the "real" HANDLE so
we need to properly deal with that. */
if (data[0] == SSH_FXP_STATUS) {
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Failed opening remote file", 0);
int badness = 1;
sftp->last_errno = libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);
return NULL;
if(LIBSSH2_FX_OK == sftp->last_errno) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "got HANDLE FXOK!");
/* silly situation, but check for a HANDLE */
rc = sftp_packet_require(sftp, SSH_FXP_HANDLE,
sftp->open_request_id, &data, &data_len);
if(rc == PACKET_EAGAIN) {
/* go back to sent state and wait for something else */
sftp->open_state = libssh2_NB_state_sent;
return NULL;
}
else if(!rc)
/* we got the handle so this is not a bad situation */
badness = 0;
}
if(badness) {
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"Failed opening remote file", 0);
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "got FXP_STATUS %d",
sftp->last_errno);
LIBSSH2_FREE(session, data);
return NULL;
}
}
fp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP_HANDLE));
@ -935,7 +976,8 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session;
unsigned long data_len, request_id = 0;
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) + offset(8) + length(4) */
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
offset(8) + length(4) */
ssize_t packet_len = handle->handle_len + 25;
unsigned char *packet, *s, *data;
static const unsigned char read_responses[2] =
@ -970,7 +1012,8 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
* So we request data by pieces.
*/
bytes_requested = buffer_maxlen - total_read;
/* 10 = packet_type(1)+request_id(4)+data_length(4)+end_of_line_flag(1) */
/* 10 = packet_type(1) + request_id(4) + data_length(4) +
end_of_line_flag(1) */
if (bytes_requested > LIBSSH2_SFTP_PACKET_MAXLEN - 10) {
bytes_requested = LIBSSH2_SFTP_PACKET_MAXLEN - 10;
}
@ -1012,6 +1055,8 @@ libssh2_sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
sftp->read_total_read = total_read;
return PACKET_EAGAIN;
} else if (packet_len != retcode) {
/* TODO: a partial write is not a critical error when in
non-blocking mode! */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet);
@ -1359,8 +1404,8 @@ libssh2_sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
sftp->write_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->write_request_id, &data, &data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->write_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@ -1585,9 +1630,9 @@ libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE * handle)
}
if (handle->close_state == libssh2_NB_state_sent) {
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
handle->close_request_id, &data,
&data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
handle->close_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@ -1696,12 +1741,13 @@ libssh2_sftp_unlink_ex(LIBSSH2_SFTP * sftp, const char *filename,
sftp->unlink_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->unlink_request_id, &data,
&data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->unlink_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
}
else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT,
"Timeout waiting for status message", 0);
sftp->unlink_state = libssh2_NB_state_idle;
@ -1805,9 +1851,9 @@ libssh2_sftp_rename_ex(LIBSSH2_SFTP * sftp, const char *source_filename,
sftp->rename_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rename_request_id, &data,
&data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rename_request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@ -1921,8 +1967,8 @@ libssh2_sftp_mkdir_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->mkdir_packet = NULL;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, request_id, &data,
&data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS, request_id, &data,
&data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {
@ -2008,8 +2054,8 @@ libssh2_sftp_rmdir_ex(LIBSSH2_SFTP * sftp, const char *path,
sftp->rmdir_state = libssh2_NB_state_sent;
}
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rmdir_request_id, &data, &data_len);
rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->rmdir_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN;
} else if (rc) {