diff options
Diffstat (limited to 'libftpconn/names.c')
-rw-r--r-- | libftpconn/names.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/libftpconn/names.c b/libftpconn/names.c index ced741f6..2d631bf9 100644 --- a/libftpconn/names.c +++ b/libftpconn/names.c @@ -31,6 +31,8 @@ struct get_names_state size_t name_alloced; /* Allocated size of NAME (>= NAME_LEN). */ int name_partial; /* True if NAME isn't complete. */ + char *dir; /* Directory being listed. */ + size_t buf_len; /* Length of contents in BUF. */ char buf[7000]; }; @@ -48,6 +50,19 @@ ftp_conn_start_get_names (struct ftp_conn *conn, if (! s) return ENOMEM; + if (conn->syshooks.fix_nlist_name) + /* We only need save the directory name if calling this hook. */ + { + s->dir = strdup (name); + if (! s->dir) + { + free (s); + return ENOMEM; + } + } + else + s->dir = 0; + err = ftp_conn_start_list (conn, name, fd); if (err) @@ -141,8 +156,23 @@ ftp_conn_cont_get_names (struct ftp_conn *conn, int fd, void *state, if (nl) { + /* Fixup any screwy names returned by the server. */ + char *name = s->name; + + if (conn->syshooks.fix_nlist_name) + { + err = (*conn->syshooks.fix_nlist_name) (conn, s->dir, &name); + if (err) + goto finished; + } + /* Call the callback function to process the current entry. */ - err = (*add_name) (s->name, hook); + err = (*add_name) (name, hook); + + if (name < s->name || name > s->name + s->name_len) + /* User-allocated NAME from the fix_nlist_name hook. */ + free (name); + if (err) goto finished; @@ -181,9 +211,18 @@ finished: return. */ if (s->name) free (s->name); + if (s->dir) + free (s->dir); free (s); close (fd); + if (err && rd > 0) + ftp_conn_abort (conn); + else if (err) + ftp_conn_finish_transfer (conn); + else + err = ftp_conn_finish_transfer (conn); + return err; } @@ -191,7 +230,7 @@ finished: (HOOK is passed to ADD_NAME). This function may block. */ error_t ftp_conn_get_names (struct ftp_conn *conn, const char *name, - ftp_conn_add_name_fun_t add_name, void *hook) + ftp_conn_add_name_fun_t add_name, void *hook) { int fd; void *state; |