First, only try to send max packet size *4 to channel write, as trying to send
much larger packages only cause internal problems and much larger allocations. Also fix sftp_write() when _libssh2_channel_write() returns that a packet was only partially sent as that is not an error. Fixed a few error messages to more accurately point out the problem
Этот коммит содержится в:
родитель
b95fe985af
Коммит
b755f3eb10
46
src/sftp.c
46
src/sftp.c
@ -1105,7 +1105,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
|||||||
/* TODO: a partial write is not a critical error when in
|
/* TODO: a partial write is not a critical error when in
|
||||||
non-blocking mode! */
|
non-blocking mode! */
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
"Unable to send FXP_READ command", 0);
|
"_libssh2_channel_write() failed", 0);
|
||||||
sftp->read_packet = NULL;
|
sftp->read_packet = NULL;
|
||||||
sftp->read_state = libssh2_NB_state_idle;
|
sftp->read_state = libssh2_NB_state_idle;
|
||||||
return -1;
|
return -1;
|
||||||
@ -1305,7 +1305,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
|
|||||||
}
|
}
|
||||||
else if (packet_len != retcode) {
|
else if (packet_len != retcode) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
"Unable to send FXP_READ command", 0);
|
"_libssh2_channel_write() failed", 0);
|
||||||
LIBSSH2_FREE(session, sftp->readdir_packet);
|
LIBSSH2_FREE(session, sftp->readdir_packet);
|
||||||
sftp->readdir_packet = NULL;
|
sftp->readdir_packet = NULL;
|
||||||
sftp->readdir_state = libssh2_NB_state_idle;
|
sftp->readdir_state = libssh2_NB_state_idle;
|
||||||
@ -1409,10 +1409,12 @@ libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *hnd, char *buffer,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sftp_write
|
/*
|
||||||
* Write data to a file handle
|
* sftp_write
|
||||||
|
*
|
||||||
|
* Write data to an SFTP handle
|
||||||
*/
|
*/
|
||||||
static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
|
static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
|
||||||
size_t count)
|
size_t count)
|
||||||
{
|
{
|
||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
@ -1421,20 +1423,28 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
|
|||||||
unsigned long data_len, retcode;
|
unsigned long data_len, retcode;
|
||||||
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
|
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) +
|
||||||
offset(8) + count(4) */
|
offset(8) + count(4) */
|
||||||
ssize_t packet_len = handle->handle_len + count + 25;
|
ssize_t packet_len;
|
||||||
unsigned char *s, *data;
|
unsigned char *s, *data;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* There's no point in us accepting a VERY large packet here since we
|
||||||
|
cannot send it anyway. We just accept 4 times the big size to fill up
|
||||||
|
the queue somewhat. */
|
||||||
|
|
||||||
|
if(count > (MAX_SSH_PACKET_LEN*4))
|
||||||
|
count = MAX_SSH_PACKET_LEN*4;
|
||||||
|
|
||||||
|
packet_len = handle->handle_len + count + 25;
|
||||||
|
|
||||||
if (sftp->write_state == libssh2_NB_state_idle) {
|
if (sftp->write_state == libssh2_NB_state_idle) {
|
||||||
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes",
|
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes",
|
||||||
(unsigned long) count);
|
(unsigned long) count);
|
||||||
s = sftp->write_packet = LIBSSH2_ALLOC(session, packet_len);
|
s = sftp->write_packet = LIBSSH2_ALLOC(session, packet_len);
|
||||||
if (!sftp->write_packet) {
|
if (!sftp->write_packet) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
"Unable to allocate memory for FXP_WRITE packet", 0);
|
"Unable to allocate memory for FXP_WRITE", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_libssh2_htonu32(s, packet_len - 4);
|
_libssh2_htonu32(s, packet_len - 4);
|
||||||
s += 4;
|
s += 4;
|
||||||
*(s++) = SSH_FXP_WRITE;
|
*(s++) = SSH_FXP_WRITE;
|
||||||
@ -1456,19 +1466,23 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE * handle, const char *buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sftp->write_state == libssh2_NB_state_created) {
|
if (sftp->write_state == libssh2_NB_state_created) {
|
||||||
rc = _libssh2_channel_write(channel, 0, (char *) sftp->write_packet,
|
rc = _libssh2_channel_write(channel, 0, (char *)sftp->write_packet,
|
||||||
packet_len);
|
packet_len);
|
||||||
if (rc == PACKET_EAGAIN) {
|
if (rc == PACKET_EAGAIN) {
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
if (packet_len != rc) {
|
else if(rc < 0) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
/* an actual error */
|
||||||
"Unable to send FXP_READ command", 0);
|
return rc;
|
||||||
LIBSSH2_FREE(session, sftp->write_packet);
|
}
|
||||||
sftp->write_packet = NULL;
|
else if(0 == rc) {
|
||||||
sftp->write_state = libssh2_NB_state_idle;
|
/* an actual error */
|
||||||
|
fprintf(stderr, "WEIRDNESS\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
else if (packet_len != rc) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
LIBSSH2_FREE(session, sftp->write_packet);
|
LIBSSH2_FREE(session, sftp->write_packet);
|
||||||
sftp->write_packet = NULL;
|
sftp->write_packet = NULL;
|
||||||
sftp->write_state = libssh2_NB_state_sent;
|
sftp->write_state = libssh2_NB_state_sent;
|
||||||
@ -2084,7 +2098,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
|
|||||||
}
|
}
|
||||||
if (packet_len != rc) {
|
if (packet_len != rc) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
"Unable to send FXP_READ command", 0);
|
"_libssh2_channel_write() failed", 0);
|
||||||
LIBSSH2_FREE(session, packet);
|
LIBSSH2_FREE(session, packet);
|
||||||
sftp->mkdir_state = libssh2_NB_state_idle;
|
sftp->mkdir_state = libssh2_NB_state_idle;
|
||||||
return -1;
|
return -1;
|
||||||
|
Загрузка…
Ссылка в новой задаче
Block a user