1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-11-23 01:22:37 +03:00

Added some clarifying comments on how the 'sftpInit_sftp' and

'sftpInit_channel' struct fields within the session struct are used. And made
sure to clear them both correctly when sftp_init() returns instead of at
shutdown time, as it must not touch them at shutdown time. This should make it
possible to properly make more than one SFTP handle.
This commit is contained in:
Daniel Stenberg
2009-05-25 10:50:49 +02:00
parent 6ff83eab1b
commit 5a162ad9f8

View File

@@ -558,18 +558,31 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
unsigned char *data, *s; unsigned char *data, *s;
unsigned long data_len; unsigned long data_len;
int rc; int rc;
LIBSSH2_SFTP *sftp_handle;
if (session->sftpInit_state == libssh2_NB_state_idle) { if (session->sftpInit_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, _libssh2_debug(session, LIBSSH2_DBG_SFTP,
"Initializing SFTP subsystem"); "Initializing SFTP subsystem");
/*
* The 'sftpInit_sftp' and 'sftpInit_channel' struct fields within the
* seeesion struct are only to be used during the setup phase. As soon
* as the SFTP session is created they are cleared and can thus be
* re-used again to allow any amount of SFTP handles per sessions.
*
* Note that you MUST NOT try to call libssh2_sftp_init() to get
* another handle until the previous one has finished and either
* succesffully made a handle or failed and returned error (not
* including *EAGAIN).
*/
assert(session->sftpInit_sftp == NULL); assert(session->sftpInit_sftp == NULL);
session->sftpInit_sftp = NULL; session->sftpInit_sftp = NULL;
session->sftpInit_state = libssh2_NB_state_created; session->sftpInit_state = libssh2_NB_state_created;
} }
sftp_handle = session->sftpInit_sftp;
if (session->sftpInit_state == libssh2_NB_state_created) { if (session->sftpInit_state == libssh2_NB_state_created) {
session->sftpInit_channel = session->sftpInit_channel =
_libssh2_channel_open(session, "session", sizeof("session") - 1, _libssh2_channel_open(session, "session", sizeof("session") - 1,
@@ -618,15 +631,17 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
return NULL; return NULL;
} }
session->sftpInit_sftp = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP)); sftp_handle =
if (!session->sftpInit_sftp) { session->sftpInit_sftp =
LIBSSH2_ALLOC(session, sizeof(LIBSSH2_SFTP));
if (!sftp_handle) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate a new SFTP structure", 0); "Unable to allocate a new SFTP structure", 0);
goto sftp_init_error; goto sftp_init_error;
} }
memset(session->sftpInit_sftp, 0, sizeof(LIBSSH2_SFTP)); memset(sftp_handle, 0, sizeof(LIBSSH2_SFTP));
session->sftpInit_sftp->channel = session->sftpInit_channel; sftp_handle->channel = session->sftpInit_channel;
session->sftpInit_sftp->request_id = 0; sftp_handle->request_id = 0;
_libssh2_htonu32(session->sftpInit_buffer, 5); _libssh2_htonu32(session->sftpInit_buffer, 5);
session->sftpInit_buffer[4] = SSH_FXP_INIT; session->sftpInit_buffer[4] = SSH_FXP_INIT;
@@ -655,7 +670,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
session->sftpInit_state = libssh2_NB_state_sent3; session->sftpInit_state = libssh2_NB_state_sent3;
} }
rc = sftp_packet_require(session->sftpInit_sftp, SSH_FXP_VERSION, rc = sftp_packet_require(sftp_handle, SSH_FXP_VERSION,
0, &data, &data_len); 0, &data, &data_len);
if (rc == PACKET_EAGAIN) { if (rc == PACKET_EAGAIN) {
libssh2_error(session, LIBSSH2_ERROR_EAGAIN, libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
@@ -674,17 +689,17 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
} }
s = data + 1; s = data + 1;
session->sftpInit_sftp->version = _libssh2_ntohu32(s); sftp_handle->version = _libssh2_ntohu32(s);
s += 4; s += 4;
if (session->sftpInit_sftp->version > LIBSSH2_SFTP_VERSION) { if (sftp_handle->version > LIBSSH2_SFTP_VERSION) {
_libssh2_debug(session, LIBSSH2_DBG_SFTP, _libssh2_debug(session, LIBSSH2_DBG_SFTP,
"Truncating remote SFTP version from %lu", "Truncating remote SFTP version from %lu",
session->sftpInit_sftp->version); sftp_handle->version);
session->sftpInit_sftp->version = LIBSSH2_SFTP_VERSION; sftp_handle->version = LIBSSH2_SFTP_VERSION;
} }
_libssh2_debug(session, LIBSSH2_DBG_SFTP, _libssh2_debug(session, LIBSSH2_DBG_SFTP,
"Enabling SFTP version %lu compatability", "Enabling SFTP version %lu compatability",
session->sftpInit_sftp->version); sftp_handle->version);
while (s < (data + data_len)) { while (s < (data + data_len)) {
unsigned char *extension_name, *extension_data; unsigned char *extension_name, *extension_data;
unsigned long extname_len, extdata_len; unsigned long extname_len, extdata_len;
@@ -705,11 +720,16 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
/* Make sure that when the channel gets closed, the SFTP service is shut /* Make sure that when the channel gets closed, the SFTP service is shut
down too */ down too */
session->sftpInit_sftp->channel->abstract = session->sftpInit_sftp; sftp_handle->channel->abstract = sftp_handle;
session->sftpInit_sftp->channel->close_cb = libssh2_sftp_dtor; sftp_handle->channel->close_cb = libssh2_sftp_dtor;
session->sftpInit_state = libssh2_NB_state_idle; session->sftpInit_state = libssh2_NB_state_idle;
return session->sftpInit_sftp;
/* clear the sftp and channel pointers in this session struct now */
session->sftpInit_sftp = NULL;
session->sftpInit_channel = NULL;
return sftp_handle;
sftp_init_error: sftp_init_error:
while (_libssh2_channel_free(session->sftpInit_channel) == PACKET_EAGAIN); while (_libssh2_channel_free(session->sftpInit_channel) == PACKET_EAGAIN);
@@ -794,10 +814,6 @@ sftp_shutdown(LIBSSH2_SFTP *sftp)
rc = _libssh2_channel_free(sftp->channel); rc = _libssh2_channel_free(sftp->channel);
/* the SFTP stuff is freed by the stored "destructor" as part of the
channel free magic */
session->sftpInit_sftp = NULL;
return rc; return rc;
} }