1
1

Make libssh2_sftp_write() be fully non-blocking. The state of the socket

is fully honored.  LIBSSH2SFTP_EAGAIN is returned when the call would
block.
Этот коммит содержится в:
James Housley 2007-06-06 19:52:11 +00:00
родитель 4b8db8c1ab
Коммит d141ba49f3
5 изменённых файлов: 70 добавлений и 165 удалений

Просмотреть файл

@ -1,5 +1,5 @@
/* /*
* $Id: sftp_RW_nonblock.c,v 1.4 2007/06/06 12:34:08 jehousley Exp $ * $Id: sftp_RW_nonblock.c,v 1.5 2007/06/06 19:52:11 jehousley Exp $
* *
* Sample showing how to do SFTP transfers in a non-blocking manner. * Sample showing how to do SFTP transfers in a non-blocking manner.
* *
@ -241,7 +241,7 @@ int main(int argc, char *argv[])
do { do {
/* write data in a loop until we block */ /* write data in a loop until we block */
rc = libssh2_sftp_writenb(sftp_handle, ptr, rc = libssh2_sftp_write(sftp_handle, ptr,
nread); nread);
ptr += rc; ptr += rc;
nread -= nread; nread -= nread;

Просмотреть файл

@ -1,5 +1,5 @@
/* /*
* $Id: sftp_write_nonblock.c,v 1.4 2007/06/06 12:34:09 jehousley Exp $ * $Id: sftp_write_nonblock.c,v 1.5 2007/06/06 19:52:11 jehousley Exp $
* *
* Sample showing how to do SFTP non-blocking write transfers. * Sample showing how to do SFTP non-blocking write transfers.
* *
@ -196,7 +196,7 @@ int main(int argc, char *argv[])
do { do {
/* write data in a loop until we block */ /* write data in a loop until we block */
while ((rc = libssh2_sftp_writenb(sftp_handle, ptr, nread)) == LIBSSH2SFTP_EAGAIN) { while ((rc = libssh2_sftp_write(sftp_handle, ptr, nread)) == LIBSSH2SFTP_EAGAIN) {
; ;
} }
ptr += rc; ptr += rc;

Просмотреть файл

@ -198,10 +198,7 @@ LIBSSH2_API int libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
LIBSSH2_API int libssh2_sftp_readdirnb(LIBSSH2_SFTP_HANDLE *handle, char *buffer, LIBSSH2_API int libssh2_sftp_readdirnb(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
size_t buffer_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs); size_t buffer_maxlen, LIBSSH2_SFTP_ATTRIBUTES *attrs);
LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, size_t count);
const char *buffer, size_t count);
LIBSSH2_API ssize_t libssh2_sftp_writenb(LIBSSH2_SFTP_HANDLE *handle,
const char *buffer, size_t count);
LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle); LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);
#define libssh2_sftp_close(handle) libssh2_sftp_close_handle(handle) #define libssh2_sftp_close(handle) libssh2_sftp_close_handle(handle)

Просмотреть файл

@ -447,31 +447,6 @@ struct _LIBSSH2_PUBLICKEY {
unsigned long listFetch_data_len; unsigned long listFetch_data_len;
}; };
typedef enum {
sftp_read_idle = 0,
sftp_read_packet_allocated,
sftp_read_packet_created,
sftp_read_packet_sent
} libssh2_sftp_read_state;
typedef enum {
sftp_readdir_idle = 0,
sftp_readdir_packet_created,
sftp_readdir_packet_sent
} libssh2_sftp_readdir_state;
typedef enum {
sftp_write_idle = 0,
sftp_write_packet_created,
sftp_write_packet_sent
} libssh2_sftp_write_state;
typedef enum {
sftp_mkdir_idle = 0,
sftp_mkdir_packet_created,
sftp_mkdir_packet_sent
} libssh2_sftp_mkdir_state;
struct _LIBSSH2_SFTP_HANDLE { struct _LIBSSH2_SFTP_HANDLE {
LIBSSH2_SFTP *sftp; LIBSSH2_SFTP *sftp;
LIBSSH2_SFTP_HANDLE *prev, *next; LIBSSH2_SFTP_HANDLE *prev, *next;
@ -513,23 +488,23 @@ struct _LIBSSH2_SFTP {
time_t requirev_start; time_t requirev_start;
/* State variables used in _libssh2_sftp_read() */ /* State variables used in _libssh2_sftp_read() */
libssh2_sftp_read_state read_state; libssh2_nonblocking_states read_state;
unsigned char *read_packet; unsigned char *read_packet;
unsigned long read_request_id; unsigned long read_request_id;
size_t read_total_read; size_t read_total_read;
/* State variables used in _libssh2_sftp_readdir() */ /* State variables used in _libssh2_sftp_readdir() */
libssh2_sftp_readdir_state readdir_state; libssh2_nonblocking_states readdir_state;
unsigned char *readdir_packet; unsigned char *readdir_packet;
unsigned long readdir_request_id; unsigned long readdir_request_id;
/* State variables used in _libssh2_sftp_write() */ /* State variables used in _libssh2_sftp_write() */
libssh2_sftp_write_state write_state; libssh2_nonblocking_states write_state;
unsigned char *write_packet; unsigned char *write_packet;
unsigned long write_request_id; unsigned long write_request_id;
/* State variables used in _libssh2_sftp_mkdir() */ /* State variables used in _libssh2_sftp_mkdir() */
libssh2_sftp_mkdir_state mkdir_state; libssh2_nonblocking_states mkdir_state;
unsigned char *mkdir_packet; unsigned char *mkdir_packet;
unsigned long mkdir_request_id; unsigned long mkdir_request_id;

Просмотреть файл

@ -793,14 +793,14 @@ static ssize_t _libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
size_t total_read = 0; size_t total_read = 0;
int retcode; int retcode;
if (sftp->read_state == sftp_read_idle) { if (sftp->read_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Reading %lu bytes from SFTP handle", (unsigned long)buffer_maxlen); _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Reading %lu bytes from SFTP handle", (unsigned long)buffer_maxlen);
packet = LIBSSH2_ALLOC(session, packet_len); packet = LIBSSH2_ALLOC(session, packet_len);
if (!packet) { if (!packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_CLOSE packet", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_CLOSE packet", 0);
return -1; return -1;
} }
sftp->read_state = sftp_read_packet_allocated; sftp->read_state = libssh2_NB_state_allocated;
} else { } else {
packet = sftp->read_packet; packet = sftp->read_packet;
request_id = sftp->read_request_id; request_id = sftp->read_request_id;
@ -824,7 +824,7 @@ static ssize_t _libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requesting %lu bytes from SFTP handle", (unsigned long)bytes_requested); _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Requesting %lu bytes from SFTP handle", (unsigned long)bytes_requested);
#endif #endif
if (sftp->read_state == sftp_read_packet_allocated) { if (sftp->read_state == libssh2_NB_state_allocated) {
libssh2_htonu32(s, packet_len - 4); libssh2_htonu32(s, packet_len - 4);
s += 4; s += 4;
*(s++) = SSH_FXP_READ; *(s++) = SSH_FXP_READ;
@ -843,17 +843,17 @@ static ssize_t _libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
libssh2_htonu32(s, buffer_maxlen); libssh2_htonu32(s, buffer_maxlen);
s += 4; s += 4;
sftp->read_state = sftp_read_packet_created; sftp->read_state = libssh2_NB_state_created;
} }
if (sftp->read_state != sftp_read_packet_sent) { if (sftp->read_state != libssh2_NB_state_sent) {
if (libssh2_session_get_blocking(channel->session)) { if (libssh2_session_get_blocking(channel->session)) {
while ((retcode = libssh2_channel_write_ex(channel, 0, (char *)packet, packet_len)) == PACKET_EAGAIN); while ((retcode = libssh2_channel_write_ex(channel, 0, (char *)packet, packet_len)) == PACKET_EAGAIN);
if (packet_len != retcode) { if (packet_len != retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = sftp_read_idle; sftp->read_state = libssh2_NB_state_idle;
return -1; return -1;
} }
} else { } else {
@ -867,14 +867,14 @@ static ssize_t _libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = sftp_read_idle; sftp->read_state = libssh2_NB_state_idle;
return -1; return -1;
} }
} }
sftp->read_packet = packet; sftp->read_packet = packet;
sftp->read_request_id = request_id; sftp->read_request_id = request_id;
sftp->read_total_read = total_read; sftp->read_total_read = total_read;
sftp->read_state = sftp_read_packet_sent; sftp->read_state = libssh2_NB_state_sent;
} }
retcode = libssh2_sftp_packet_requirev(sftp, 2, read_responses, request_id, &data, &data_len); retcode = libssh2_sftp_packet_requirev(sftp, 2, read_responses, request_id, &data, &data_len);
@ -885,7 +885,7 @@ static ssize_t _libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for status message", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for status message", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = sftp_read_idle; sftp->read_state = libssh2_NB_state_idle;
return -1; return -1;
} }
@ -895,7 +895,7 @@ static ssize_t _libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = sftp_read_idle; sftp->read_state = libssh2_NB_state_idle;
if (retcode == LIBSSH2_FX_EOF) { if (retcode == LIBSSH2_FX_EOF) {
return total_read; return total_read;
@ -910,7 +910,7 @@ static ssize_t _libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
if (bytes_read > (data_len - 9)) { if (bytes_read > (data_len - 9)) {
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = sftp_read_idle; sftp->read_state = libssh2_NB_state_idle;
return -1; return -1;
} }
#ifdef LIBSSH2_DEBUG_SFTP #ifdef LIBSSH2_DEBUG_SFTP
@ -924,13 +924,13 @@ static ssize_t _libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
* Set the state back to allocated, so a new one will be * Set the state back to allocated, so a new one will be
* created to either request more data or get EOF * created to either request more data or get EOF
*/ */
sftp->read_state = sftp_read_packet_allocated; sftp->read_state = libssh2_NB_state_allocated;
} }
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->read_packet = NULL; sftp->read_packet = NULL;
sftp->read_state = sftp_read_idle; sftp->read_state = libssh2_NB_state_idle;
return total_read; return total_read;
} }
/* {{{ libssh2_sftp_read /* {{{ libssh2_sftp_read
@ -1003,7 +1003,7 @@ static int _libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size
unsigned char read_responses[2] = { SSH_FXP_NAME, SSH_FXP_STATUS }; unsigned char read_responses[2] = { SSH_FXP_NAME, SSH_FXP_STATUS };
int retcode; int retcode;
if (sftp->readdir_state == sftp_readdir_idle) { if (sftp->readdir_state == libssh2_NB_state_idle) {
if (handle->u.dir.names_left) { if (handle->u.dir.names_left) {
/* /*
* A prior request returned more than one directory entry, * A prior request returned more than one directory entry,
@ -1062,23 +1062,23 @@ static int _libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size
memcpy(s, handle->handle, handle->handle_len); memcpy(s, handle->handle, handle->handle_len);
s += handle->handle_len; s += handle->handle_len;
sftp->readdir_state = sftp_readdir_packet_created; sftp->readdir_state = libssh2_NB_state_created;
} }
else if (sftp->readdir_state == sftp_readdir_packet_created) { else if (sftp->readdir_state == libssh2_NB_state_created) {
packet = sftp->readdir_packet; packet = sftp->readdir_packet;
request_id = sftp->readdir_request_id; request_id = sftp->readdir_request_id;
sftp->readdir_packet = NULL; sftp->readdir_packet = NULL;
} }
if (sftp->readdir_state != sftp_readdir_packet_sent) { if (sftp->readdir_state != libssh2_NB_state_sent) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Reading entries from directory handle"); _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Reading entries from directory handle");
if (libssh2_session_get_blocking(channel->session)) { if (libssh2_session_get_blocking(channel->session)) {
while ((retcode = libssh2_channel_write_ex(channel, 0, (char *)packet, packet_len)) == PACKET_EAGAIN); while ((retcode = libssh2_channel_write_ex(channel, 0, (char *)packet, packet_len)) == PACKET_EAGAIN);
if (packet_len != retcode) { if (packet_len != retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->readdir_state = sftp_readdir_idle; sftp->readdir_state = libssh2_NB_state_idle;
return -1; return -1;
} }
} else { } else {
@ -1090,13 +1090,13 @@ static int _libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size
else if (packet_len != retcode) { else if (packet_len != retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->readdir_state = sftp_readdir_idle; sftp->readdir_state = libssh2_NB_state_idle;
return -1; return -1;
} }
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->readdir_state = sftp_readdir_packet_sent; sftp->readdir_state = libssh2_NB_state_sent;
sftp->readdir_packet = NULL; sftp->readdir_packet = NULL;
} }
@ -1106,7 +1106,7 @@ static int _libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size
} }
else if (retcode) { else if (retcode) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for status message", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for status message", 0);
sftp->readdir_state = sftp_readdir_idle; sftp->readdir_state = libssh2_NB_state_idle;
return -1; return -1;
} }
@ -1114,12 +1114,12 @@ static int _libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size
retcode = libssh2_ntohu32(data + 5); retcode = libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
if (retcode == LIBSSH2_FX_EOF) { if (retcode == LIBSSH2_FX_EOF) {
sftp->readdir_state = sftp_readdir_idle; sftp->readdir_state = libssh2_NB_state_idle;
return 0; return 0;
} else { } else {
sftp->last_errno = retcode; sftp->last_errno = retcode;
libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0); libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, "SFTP Protocol Error", 0);
sftp->readdir_state = sftp_readdir_idle; sftp->readdir_state = libssh2_NB_state_idle;
return -1; return -1;
} }
} }
@ -1128,7 +1128,7 @@ static int _libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu entries returned", num_names); _libssh2_debug(session, LIBSSH2_DBG_SFTP, "%lu entries returned", num_names);
if (num_names <= 0) { if (num_names <= 0) {
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
sftp->readdir_state = sftp_readdir_idle; sftp->readdir_state = libssh2_NB_state_idle;
return (num_names == 0) ? 0 : -1; return (num_names == 0) ? 0 : -1;
} }
@ -1153,7 +1153,7 @@ static int _libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size
} }
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
sftp->readdir_state = sftp_readdir_idle; sftp->readdir_state = libssh2_NB_state_idle;
return filename_len; return filename_len;
} }
@ -1161,7 +1161,7 @@ static int _libssh2_sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size
handle->u.dir.names_packet = data; handle->u.dir.names_packet = data;
handle->u.dir.next_name = (char *)data + 9; handle->u.dir.next_name = (char *)data + 9;
sftp->readdir_state = sftp_readdir_idle; sftp->readdir_state = libssh2_NB_state_idle;
/* Be lazy, just use the name popping mechanism from the start of the function */ /* Be lazy, just use the name popping mechanism from the start of the function */
return libssh2_sftp_readdir(handle, buffer, buffer_maxlen, attrs); return libssh2_sftp_readdir(handle, buffer, buffer_maxlen, attrs);
@ -1220,83 +1220,68 @@ LIBSSH2_API int libssh2_sftp_readdirnb(LIBSSH2_SFTP_HANDLE *handle, char *buffer
} }
/* }}} */ /* }}} */
/* {{{ _libssh2_sftp_write /* {{{ libssh2_sftp_write
* Write data to a file handle * Write data to a file handle
*/ */
/* _libssh2_sftp_write - NB-SAFE */ LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, size_t count)
static ssize_t _libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, size_t count)
{ {
LIBSSH2_SFTP *sftp = handle->sftp; LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel; LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
unsigned long data_len, request_id, retcode; unsigned long data_len, retcode;
/* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) + offset(8) + count(4) */ /* 25 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) + offset(8) + count(4) */
ssize_t packet_len = handle->handle_len + count + 25; ssize_t packet_len = handle->handle_len + count + 25;
unsigned char *packet, *s, *data; unsigned char *s, *data;
int rc; int rc;
if (sftp->write_state == sftp_write_idle) { if (sftp->write_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes", (unsigned long)count); _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Writing %lu bytes", (unsigned long)count);
s = packet = LIBSSH2_ALLOC(session, packet_len); s = sftp->write_packet = LIBSSH2_ALLOC(session, packet_len);
if (!packet) { if (!sftp->write_packet) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_WRITE packet", 0); libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for FXP_WRITE packet", 0);
return -1; return -1;
} }
libssh2_htonu32(s, packet_len - 4); s += 4; libssh2_htonu32(s, packet_len - 4); s += 4;
*(s++) = SSH_FXP_WRITE; *(s++) = SSH_FXP_WRITE;
request_id = sftp->request_id++; sftp->write_request_id = sftp->request_id++;
libssh2_htonu32(s, request_id); s += 4; libssh2_htonu32(s, sftp->write_request_id); s += 4;
libssh2_htonu32(s, handle->handle_len); s += 4; libssh2_htonu32(s, handle->handle_len); s += 4;
memcpy(s, handle->handle, handle->handle_len); s += handle->handle_len; memcpy(s, handle->handle, handle->handle_len); s += handle->handle_len;
libssh2_htonu64(s, handle->u.file.offset); s += 8; libssh2_htonu64(s, handle->u.file.offset); s += 8;
libssh2_htonu32(s, count); s += 4; libssh2_htonu32(s, count); s += 4;
memcpy(s, buffer, count); s += count; memcpy(s, buffer, count); s += count;
sftp->write_state = sftp_write_packet_created; sftp->write_state = libssh2_NB_state_created;
} else {
packet = sftp->write_packet;
request_id = sftp->write_request_id;
} }
if (sftp->write_state != sftp_write_packet_sent) { if (sftp->write_state == libssh2_NB_state_created) {
if (libssh2_session_get_blocking(channel->session)) { if ((rc = libssh2_channel_write_ex(channel, 0, (char *)sftp->write_packet, packet_len)) == PACKET_EAGAIN) {
while ((rc = libssh2_channel_write_ex(channel, 0, (char *)packet, packet_len)) == PACKET_EAGAIN); return PACKET_EAGAIN;
if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet);
sftp->write_state = sftp_write_idle;
return -1;
}
} else {
if ((rc = libssh2_channel_write_ex(channel, 0, (char *)packet, packet_len)) == PACKET_EAGAIN) {
sftp->write_packet = packet;
sftp->write_request_id = request_id;
return PACKET_EAGAIN;
}
if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet);
sftp->write_state = sftp_write_idle;
return -1;
}
} }
LIBSSH2_FREE(session, packet); if (packet_len != rc) {
sftp->write_state = sftp_write_packet_sent; libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, sftp->write_packet);
sftp->write_packet = NULL;
sftp->write_state = libssh2_NB_state_idle;
return -1;
}
LIBSSH2_FREE(session, sftp->write_packet);
sftp->write_packet = NULL; sftp->write_packet = NULL;
sftp->write_state = libssh2_NB_state_sent;
} }
rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, request_id, &data, &data_len); rc = libssh2_sftp_packet_require(sftp, SSH_FXP_STATUS, sftp->write_request_id, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
return PACKET_EAGAIN; return PACKET_EAGAIN;
} }
else if (rc) { else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for status message", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for status message", 0);
sftp->write_state = sftp_write_idle; sftp->write_state = libssh2_NB_state_idle;
return -1; return -1;
} }
sftp->write_state = sftp_write_idle; sftp->write_state = libssh2_NB_state_idle;
retcode = libssh2_ntohu32(data + 5); retcode = libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
@ -1312,58 +1297,6 @@ static ssize_t _libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buff
} }
/* }}} */ /* }}} */
/* {{{ libssh2_sftp_write
* Write data to a SFTP handle blocking
*/
/* libssh2_sftp_write - NB-UNSAFE */
LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle,
const char *buffer, size_t count)
{
ssize_t rc;
LIBSSH2_CHANNEL *ch = handle->sftp->channel;
int bl = libssh2_session_get_blocking(ch->session);
/* set blocking */
libssh2_channel_set_blocking(ch, 1);
rc = _libssh2_sftp_write(handle, buffer, count);
/* restore state */
libssh2_channel_set_blocking(ch, bl);
if (rc < 0) {
/* precent accidental returning of other return codes since
this API does not support/provide those */
return -1;
}
return rc;
}
/* }}} */
/* {{{ libssh2_sftp_write
* Write data to a SFTP handle non-blocking
*/
/* libssh2_sftp_writenb - NB-SAFE */
LIBSSH2_API ssize_t libssh2_sftp_writenb(LIBSSH2_SFTP_HANDLE *handle,
const char *buffer, size_t count)
{
ssize_t rc;
LIBSSH2_CHANNEL *ch = handle->sftp->channel;
int bl = libssh2_session_get_blocking(ch->session);
/* set non-blocking */
libssh2_channel_set_blocking(ch, 0);
rc = _libssh2_sftp_write(handle, buffer, count);
/* restore state */
libssh2_channel_set_blocking(ch, bl);
return rc;
}
/* }}} */
/* {{{ libssh2_sftp_fstat_ex /* {{{ libssh2_sftp_fstat_ex
* Get or Set stat on a file * Get or Set stat on a file
*/ */
@ -1681,7 +1614,7 @@ static int _libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned
unsigned char *packet, *s, *data; unsigned char *packet, *s, *data;
int rc; int rc;
if (sftp->mkdir_state == sftp_mkdir_idle) { if (sftp->mkdir_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, "Creating directory %s with mode 0%lo", path, mode); _libssh2_debug(session, LIBSSH2_DBG_SFTP, "Creating directory %s with mode 0%lo", path, mode);
s = packet = LIBSSH2_ALLOC(session, packet_len); s = packet = LIBSSH2_ALLOC(session, packet_len);
if (!packet) { if (!packet) {
@ -1699,19 +1632,19 @@ static int _libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned
memcpy(s, path, path_len); s += path_len; memcpy(s, path, path_len); s += path_len;
s += libssh2_sftp_attr2bin(s, &attrs); s += libssh2_sftp_attr2bin(s, &attrs);
sftp->mkdir_state = sftp_mkdir_packet_created; sftp->mkdir_state = libssh2_NB_state_created;
} else { } else {
packet = sftp->mkdir_packet; packet = sftp->mkdir_packet;
request_id = sftp->mkdir_request_id; request_id = sftp->mkdir_request_id;
} }
if (sftp->mkdir_state != sftp_mkdir_packet_sent) { if (sftp->mkdir_state != libssh2_NB_state_created) {
if (libssh2_session_get_blocking(channel->session)) { if (libssh2_session_get_blocking(channel->session)) {
while ((rc = libssh2_channel_write_ex(channel, 0, (char *)packet, packet_len)) == PACKET_EAGAIN); while ((rc = libssh2_channel_write_ex(channel, 0, (char *)packet, packet_len)) == PACKET_EAGAIN);
if (packet_len != rc) { if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->mkdir_state = sftp_mkdir_idle; sftp->mkdir_state = libssh2_NB_state_idle;
return -1; return -1;
} }
} else { } else {
@ -1723,12 +1656,12 @@ static int _libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned
if (packet_len != rc) { if (packet_len != rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send FXP_READ command", 0);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->mkdir_state = sftp_mkdir_idle; sftp->mkdir_state = libssh2_NB_state_idle;
return -1; return -1;
} }
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
sftp->mkdir_state = sftp_mkdir_packet_sent; sftp->mkdir_state = libssh2_NB_state_sent;
sftp->mkdir_packet = NULL; sftp->mkdir_packet = NULL;
} }
@ -1738,11 +1671,11 @@ static int _libssh2_sftp_mkdir_ex(LIBSSH2_SFTP *sftp, const char *path, unsigned
} }
else if (rc) { else if (rc) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for status message", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timeout waiting for status message", 0);
sftp->mkdir_state = sftp_mkdir_idle; sftp->mkdir_state = libssh2_NB_state_idle;
return -1; return -1;
} }
sftp->mkdir_state = sftp_mkdir_idle; sftp->mkdir_state = libssh2_NB_state_idle;
retcode = libssh2_ntohu32(data + 5); retcode = libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);