diff options
Diffstat (limited to 'libftpconn/unix.c')
-rw-r--r-- | libftpconn/unix.c | 58 |
1 files changed, 30 insertions, 28 deletions
diff --git a/libftpconn/unix.c b/libftpconn/unix.c index 52cfc105..d1004429 100644 --- a/libftpconn/unix.c +++ b/libftpconn/unix.c @@ -136,10 +136,15 @@ error_t ftp_conn_unix_interp_err (struct ftp_conn *conn, const char *txt, struct get_stats_state { char *name; /* Last read (maybe partial) name. */ + size_t name_len; /* Valid length of NAME, *not including* '\0'. */ + size_t name_alloced; /* Allocated size of NAME (>= NAME_LEN). */ int name_partial; /* True if NAME isn't complete. */ + struct stat stat; /* Last read stat info. */ - size_t buf_len; /* Length of contents in BUF. */ + int start; /* True if at beginning of output. */ + + size_t buf_len; /* Length of contents in BUF. */ char buf[7000]; }; @@ -181,6 +186,7 @@ ftp_conn_unix_start_get_stats (struct ftp_conn *conn, else { s->name = 0; + s->name_len = s->name_alloced = 0; s->name_partial = 0; s->buf_len = 0; s->start = 1; @@ -512,26 +518,24 @@ ftp_conn_unix_cont_get_stats (struct ftp_conn *conn, int fd, void *state, if (name_len > 0 && p[name_len - 1] == '\r') name_len--; if (name_len > 0) - if (s->name) - /* Extending s->name. */ - { - size_t old_len = strlen (s->name); - char *new_name = realloc (s->name, old_len + name_len + 1); - if (! new_name) - goto enomem; - s->name = new_name; - strncpy (new_name + old_len, p, name_len); - new_name[old_len + name_len] = '\0'; - } - else - /* A new name. */ - { - s->name = malloc (name_len + 1); - if (! s->name) - goto enomem; - strncpy (s->name, p, name_len); - s->name[name_len] = '\0'; - } + /* Extending s->name. */ + { + size_t old_len = s->name_len; + size_t total_len = old_len + name_len + 1; + + if (total_len > s->name_alloced) + { + char *new_name = realloc (s->name, total_len); + if (! new_name) + goto enomem; + s->name = new_name; + s->name_alloced = total_len; + } + + strncpy (s->name + old_len, p, name_len); + s->name[old_len + name_len] = '\0'; + s->name_len = total_len - 1; + } if (nl) { @@ -540,13 +544,11 @@ ftp_conn_unix_cont_get_stats (struct ftp_conn *conn, int fd, void *state, if (S_ISLNK (s->stat.st_mode)) /* A symlink, see if we can find the link target. */ { - char *lsep = strstr (s->name, " -> "); - if (lsep) + symlink_target = strstr (s->name, " -> "); + if (symlink_target) { - *lsep = '\0'; - lsep += 4; - symlink_target = strdup (lsep); - s->name = realloc (s->name, (lsep - 3) - s->name); + *symlink_target = '\0'; + symlink_target += 4; } } @@ -556,7 +558,7 @@ ftp_conn_unix_cont_get_stats (struct ftp_conn *conn, int fd, void *state, if (err) goto finished; - s->name = 0; + s->name_len = 0; s->name_partial = 0; skip_line: |