diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index f8c1304..cf0ed8d 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -85,6 +85,7 @@ #include "libssh2.h" #include "libssh2_publickey.h" #include "libssh2_sftp.h" +#include "misc.h" /* for the linked list stuff */ #ifndef FALSE #define FALSE 0 @@ -547,8 +548,9 @@ struct _LIBSSH2_PUBLICKEY struct _LIBSSH2_SFTP_HANDLE { + struct list_node node; + LIBSSH2_SFTP *sftp; - LIBSSH2_SFTP_HANDLE *prev, *next; /* This is a pre-allocated buffer used for sending SFTP requests as the whole thing might not get sent in one go. This buffer is used for read, @@ -588,7 +590,8 @@ struct _LIBSSH2_SFTP LIBSSH2_PACKET_BRIGADE packets; - LIBSSH2_SFTP_HANDLE *handles; + /* a list of _LIBSSH2_SFTP_HANDLE structs */ + struct list_head sftp_handles; unsigned long last_errno; @@ -928,22 +931,6 @@ struct _LIBSSH2_SESSION #define LIBSSH2_SOCKET_RECV_FLAGS(session) 0 #endif -/* -------- */ - -/* First take towards a generic linked list handling code for libssh2 - internals */ - -struct list_head { - struct list_node *last; - struct list_node *first; -}; - -struct list_node { - struct list_node *next; - struct list_node *prev; - struct list_head *head; -}; - /* --------- */ /* libssh2 extensible ssh api, ultimately I'd like to allow loading additional diff --git a/src/misc.c b/src/misc.c index c8e58c0..adf2b0b 100644 --- a/src/misc.c +++ b/src/misc.c @@ -426,3 +426,30 @@ void _libssh2_list_remove(struct list_node *entry) else entry->head->last = entry->prev; } + +#if 0 +/* insert a node before the given 'after' entry */ +void _libssh2_list_insert(struct list_node *after, /* insert before this */ + struct list_node *entry) +{ + /* 'after' is next to 'entry' */ + bentry->next = after; + + /* entry's prev is then made to be the prev after current has */ + entry->prev = after->prev; + + /* the node that is now before 'entry' was previously before 'after' + and must be made to point to 'entry' correctly */ + if(entry->prev) + entry->prev->next = entry; + + /* after's prev entry points back to entry */ + after->prev = entry; + + /* after's next entry is still the same as before */ + + /* entry's head is the same as after's */ + entry->head = after->head; +} + +#endif diff --git a/src/misc.h b/src/misc.h index d88c893..7d3842c 100644 --- a/src/misc.h +++ b/src/misc.h @@ -38,7 +38,16 @@ * OF SUCH DAMAGE. */ -#include "libssh2_priv.h" +struct list_head { + struct list_node *last; + struct list_node *first; +}; + +struct list_node { + struct list_node *next; + struct list_node *prev; + struct list_head *head; +}; void _libssh2_list_init(struct list_head *head); @@ -58,6 +67,6 @@ void *_libssh2_list_prev(struct list_node *node); /* remove this node from the list */ void _libssh2_list_remove(struct list_node *entry); -size_t _libssh2_base64_encode(LIBSSH2_SESSION *session, +size_t _libssh2_base64_encode(struct _LIBSSH2_SESSION *session, const char *inp, size_t insize, char **outptr); #endif /* _LIBSSH2_MISC_H */ diff --git a/src/sftp.c b/src/sftp.c index cef3aa7..a3c5b95 100644 --- a/src/sftp.c +++ b/src/sftp.c @@ -556,8 +556,8 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) * 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 + * Note that you MUST NOT try to call libssh2_sftp_init() again to get + * another handle until the previous call has finished and either * succesffully made a handle or failed and returned error (not * including *EAGAIN). */ @@ -715,6 +715,8 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) session->sftpInit_sftp = NULL; session->sftpInit_channel = NULL; + _libssh2_list_init(&sftp_handle->sftp_handles); + return sftp_handle; sftp_init_error: @@ -798,6 +800,9 @@ sftp_shutdown(LIBSSH2_SFTP *sftp) sftp->symlink_packet = NULL; } + /* TODO: We should consider walking over the sftp_handles list and kill + * any remaining sftp handles ... */ + rc = _libssh2_channel_free(sftp->channel); return rc; @@ -985,12 +990,10 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, memcpy(fp->handle, data + 9, fp->handle_len); LIBSSH2_FREE(session, data); - /* Link the file and the sftp session together */ - fp->next = sftp->handles; - if (fp->next) { - fp->next->prev = fp; - } - fp->sftp = sftp; + /* add this file handle to the list kept in the sftp session */ + _libssh2_list_add(&sftp->sftp_handles, &fp->node); + + fp->sftp = sftp; /* point to the parent struct */ fp->u.file.offset = 0; @@ -1775,12 +1778,8 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle) return -1; } - if (handle == sftp->handles) { - sftp->handles = handle->next; - } - if (handle->next) { - handle->next->prev = NULL; - } + /* remove this handle from the parent's list */ + _libssh2_list_remove(&handle->node); if ((handle->handle_type == LIBSSH2_SFTP_HANDLE_DIR) && handle->u.dir.names_left) {