From 099d8ee3da3a6eea5635581ae517035165f400a5 Mon Sep 17 00:00:00 2001 From: Tim Ruehsen Date: Thu, 9 May 2013 22:37:17 +0200 Subject: [PATCH] replaced read_whole_file() by getline() --- src/ChangeLog | 15 +++++ src/cookies.c | 9 ++- src/ftp-ls.c | 164 +++++++++++++++++++++----------------------------- src/ftp.c | 142 ++++++++++++++++++++++--------------------- src/init.c | 7 ++- src/netrc.c | 50 ++------------- src/utils.c | 50 --------------- src/utils.h | 1 - 8 files changed, 170 insertions(+), 268 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 5ce9f253..fd037a1d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2013-05-14 Tim Ruehsen + + * cookies.c (cookie_jar_load): Replaced read_whole_file() by getline(). + * init.c (run_wgetrc): Likewise. + * netrc.c (parse_netrc): Likewise. + * utils.c: Likewise. + * ftp.c (getftp): Likewise. + * ftp-ls.c (ftp_parse_unix_ls, ftp_parse_winnt_ls, ftp_parse_vms_ls): Likewise. + * ftp-ls.c (clean_line): Accept the string length as parameter. + * ftp-ls.c: Replaced indent tabs by spaces. + * ftp.c: Likewise. + * utils.c: Removed read_whole_file() definition. + * netrc.c: Removed read_whole_file() definition for STANDALONE. + * utils.h: Removed read_whole_file() declaration. + 2013-05-09 Tim Ruehsen * utils.c (acceptable): use standard string functions instead of diff --git a/src/cookies.c b/src/cookies.c index 87cc554b..4efda88c 100644 --- a/src/cookies.c +++ b/src/cookies.c @@ -1129,7 +1129,9 @@ domain_port (const char *domain_b, const char *domain_e, void cookie_jar_load (struct cookie_jar *jar, const char *file) { - char *line; + char *line = NULL; + size_t bufsize = 0; + FILE *fp = fopen (file, "r"); if (!fp) { @@ -1137,9 +1139,10 @@ cookie_jar_load (struct cookie_jar *jar, const char *file) quote (file), strerror (errno)); return; } + cookies_now = time (NULL); - for (; ((line = read_whole_line (fp)) != NULL); xfree (line)) + while (getline (&line, &bufsize, fp) > 0) { struct cookie *cookie; char *p = line; @@ -1233,6 +1236,8 @@ cookie_jar_load (struct cookie_jar *jar, const char *file) abort_cookie: delete_cookie (cookie); } + + xfree(line); fclose (fp); } diff --git a/src/ftp-ls.c b/src/ftp-ls.c index 3056651b..28e32c4a 100644 --- a/src/ftp-ls.c +++ b/src/ftp-ls.c @@ -68,16 +68,17 @@ symperms (const char *s) replaces all character with . Returns the length of the modified line. */ static int -clean_line(char *line) +clean_line (char *line, int len) { - int len = strlen (line); - if (!len) return 0; - if (line[len - 1] == '\n') + if (len <= 0) return 0; + + while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) line[--len] = '\0'; + if (!len) return 0; - if (line[len - 1] == '\r') - line[--len] = '\0'; + for ( ; *line ; line++ ) if (*line == '\t') *line = ' '; + return len; } @@ -102,8 +103,9 @@ ftp_parse_unix_ls (const char *file, int ignore_perms) int hour, min, sec, ptype; struct tm timestruct, *tnow; time_t timenow; + size_t bufsize = 0; - char *line, *tok, *ptok; /* tokenizer */ + char *line = NULL, *tok, *ptok; /* tokenizer */ struct fileinfo *dir, *l, cur; /* list creation */ fp = fopen (file, "rb"); @@ -115,22 +117,16 @@ ftp_parse_unix_ls (const char *file, int ignore_perms) dir = l = NULL; /* Line loop to end of file: */ - while ((line = read_whole_line (fp)) != NULL) + while ((len = getline (&line, &bufsize, fp)) > 0) { - len = clean_line (line); + len = clean_line (line, len); /* Skip if total... */ if (!strncasecmp (line, "total", 5)) - { - xfree (line); - continue; - } + continue; /* Get the first token (permissions). */ tok = strtok (line, " "); if (!tok) - { - xfree (line); - continue; - } + continue; cur.name = NULL; cur.linkto = NULL; @@ -368,7 +364,6 @@ ftp_parse_unix_ls (const char *file, int ignore_perms) DEBUGP (("Skipping.\n")); xfree_null (cur.name); xfree_null (cur.linkto); - xfree (line); continue; } @@ -416,10 +411,9 @@ ftp_parse_unix_ls (const char *file, int ignore_perms) timestruct.tm_isdst = -1; l->tstamp = mktime (×truct); /* store the time-stamp */ l->ptype = ptype; - - xfree (line); } + xfree (line); fclose (fp); return dir; } @@ -431,9 +425,10 @@ ftp_parse_winnt_ls (const char *file) int len; int year, month, day; /* for time analysis */ int hour, min; + size_t bufsize = 0; struct tm timestruct; - char *line, *tok; /* tokenizer */ + char *line = NULL, *tok; /* tokenizer */ char *filename; struct fileinfo *dir, *l, cur; /* list creation */ @@ -446,42 +441,42 @@ ftp_parse_winnt_ls (const char *file) dir = l = NULL; /* Line loop to end of file: */ - while ((line = read_whole_line (fp)) != NULL) + while ((len = getline (&line, &bufsize, fp)) > 0) { - len = clean_line (line); + len = clean_line (line, len); /* Name begins at 39 column of the listing if date presented in `mm-dd-yy' format or at 41 column if date presented in `mm-dd-yyyy' format. Thus, we cannot extract name before we parse date. Using this information we also can recognize filenames that begin with a series of space characters (but who really wants to use such filenames anyway?). */ - if (len < 40) goto continue_loop; + if (len < 40) continue; filename = line + 39; /* First column: mm-dd-yy or mm-dd-yyyy. Should atoi() on the month fail, january will be assumed. */ tok = strtok(line, "-"); - if (tok == NULL) goto continue_loop; + if (tok == NULL) continue; month = atoi(tok) - 1; if (month < 0) month = 0; tok = strtok(NULL, "-"); - if (tok == NULL) goto continue_loop; + if (tok == NULL) continue; day = atoi(tok); tok = strtok(NULL, " "); - if (tok == NULL) goto continue_loop; + if (tok == NULL) continue; year = atoi(tok); /* Assuming the epoch starting at 1.1.1970 */ if (year <= 70) - { - year += 100; - } + { + year += 100; + } else if (year >= 1900) - { - year -= 1900; - filename += 2; - } + { + year -= 1900; + filename += 2; + } /* Now it is possible to determine the position of the first symbol in - filename. */ + filename. */ cur.name = xstrdup(filename); DEBUGP (("Name: '%s'\n", cur.name)); @@ -489,10 +484,10 @@ ftp_parse_winnt_ls (const char *file) /* Second column: hh:mm[AP]M, listing does not contain value for seconds */ tok = strtok(NULL, ":"); - if (tok == NULL) goto continue_loop; + if (tok == NULL) continue; hour = atoi(tok); tok = strtok(NULL, "M"); - if (tok == NULL) goto continue_loop; + if (tok == NULL) continue; min = atoi(tok); /* Adjust hour from AM/PM. Just for the record, the sequence goes 11:00AM, 12:00PM, 01:00PM ... 11:00PM, 12:00AM, 01:00AM . */ @@ -523,9 +518,9 @@ ftp_parse_winnt_ls (const char *file) directories as the listing does not give us a clue) and filetype here. */ tok = strtok(NULL, " "); - if (tok == NULL) goto continue_loop; + if (tok == NULL) continue; while ((tok != NULL) && (*tok == '\0')) tok = strtok(NULL, " "); - if (tok == NULL) goto continue_loop; + if (tok == NULL) continue; if (*tok == '<') { cur.type = FT_DIRECTORY; @@ -564,11 +559,9 @@ ftp_parse_winnt_ls (const char *file) memcpy (l, &cur, sizeof (cur)); l->next = NULL; } - -continue_loop: - xfree (line); } + xfree (line); fclose(fp); return dir; } @@ -689,11 +682,12 @@ ftp_parse_vms_ls (const char *file) FILE *fp; int dt, i, j, len; int perms; + size_t bufsize = 0; time_t timenow; struct tm *timestruct; char date_str[ 32]; - char *line, *tok; /* tokenizer */ + char *line = NULL, *tok; /* tokenizer */ struct fileinfo *dir, *l, cur; /* list creation */ fp = fopen (file, "r"); @@ -706,52 +700,34 @@ ftp_parse_vms_ls (const char *file) /* Skip blank lines, Directory heading, and more blank lines. */ - j = 0; /* Expecting initial blank line(s). */ - while (1) + for (j = 0; (i = getline (&line, &bufsize, fp)) > 0; ) { - line = read_whole_line (fp); - if (line == NULL) + i = clean_line (line, i); + if (i <= 0) + continue; /* Ignore blank line. */ + + if ((j == 0) && (line[i - 1] == ']')) { - break; + /* Found Directory heading line. Next non-blank line + is significant. */ + j = 1; + } + else if (!strncmp (line, "Total of ", 9)) + { + /* Found "Total of ..." footing line. No valid data + will follow (empty directory). */ + i = 0; /* Arrange for early exit. */ + break; } else { - i = clean_line (line); - if (i <= 0) - { - xfree (line); /* Free useless line storage. */ - continue; /* Blank line. Keep looking. */ - } - else - { - if ((j == 0) && (line[ i- 1] == ']')) - { - /* Found Directory heading line. Next non-blank line - is significant. - */ - j = 1; - } - else if (!strncmp (line, "Total of ", 9)) - { - /* Found "Total of ..." footing line. No valid data - will follow (empty directory). - */ - xfree (line); /* Free useless line storage. */ - line = NULL; /* Arrange for early exit. */ - break; - } - else - { - break; /* Must be significant data. */ - } - } - xfree (line); /* Free useless line storage. */ + break; /* Must be significant data. */ } } /* Read remainder of file until the next blank line or EOF. */ - while (line != NULL) + while (i > 0) { char *p; @@ -842,9 +818,8 @@ ftp_parse_vms_ls (const char *file) if (tok == NULL) { DEBUGP (("Getting additional line.\n")); - xfree (line); - line = read_whole_line (fp); - if (!line) + i = getline (&line, &bufsize, fp); + if (i <= 0) { DEBUGP (("EOF. Leaving listing parser.\n")); break; @@ -853,14 +828,14 @@ ftp_parse_vms_ls (const char *file) /* Second line must begin with " ". Otherwise, it's a first line (and we may be confused). */ + i = clean_line (line, i); if (i <= 0) { /* Blank line. End of significant file listing. */ DEBUGP (("Blank line. Leaving listing parser.\n")); - xfree (line); /* Free useless line storage. */ break; } - else if (line[ 0] != ' ') + else if (line[0] != ' ') { DEBUGP (("Non-blank in column 1. Must be a new file name?\n")); continue; @@ -872,7 +847,6 @@ ftp_parse_vms_ls (const char *file) { /* Unexpected non-empty but apparently blank line. */ DEBUGP (("Null token. Leaving listing parser.\n")); - xfree (line); /* Free useless line storage. */ break; } } @@ -911,7 +885,7 @@ ftp_parse_vms_ls (const char *file) (sizeof( date_str)- strlen (date_str) - 1)); DEBUGP (("Date time: >%s<\n", date_str)); } - else if (strchr ( tok, '[') != NULL) + else if (strchr (tok, '[') != NULL) { /* Owner. (Ignore.) */ DEBUGP (("Owner.\n")); @@ -921,7 +895,7 @@ ftp_parse_vms_ls (const char *file) /* Protections (permissions). */ perms = 0; j = 0; - for (i = 0; i < strlen( tok); i++) + for (i = 0; i < strlen(tok); i++) { switch (tok[ i]) { @@ -1015,21 +989,19 @@ ftp_parse_vms_ls (const char *file) l->next = NULL; } - /* Free old line storage. Read a new line. */ - xfree (line); - line = read_whole_line (fp); - if (line != NULL) + i = getline (&line, &bufsize, fp); + if (i > 0) { - i = clean_line (line); + i = clean_line (line, i); if (i <= 0) - { + { /* Blank line. End of significant file listing. */ - xfree (line); /* Free useless line storage. */ - break; - } + break; + } } } + xfree (line); fclose (fp); return dir; } diff --git a/src/ftp.c b/src/ftp.c index b585631f..0ad4b326 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -616,16 +616,16 @@ Error in server response, closing control connection.\n")); The VMS restriction may be relaxed when the squirrely code above is reformed. */ - if ((con->rs == ST_VMS) && (target[0] != '/')) - { - cwd_start = 0; - DEBUGP (("Using two-step CWD for relative path.\n")); - } - else - { + if ((con->rs == ST_VMS) && (target[0] != '/')) + { + cwd_start = 0; + DEBUGP (("Using two-step CWD for relative path.\n")); + } + else + { /* Go straight to the target. */ - cwd_start = 1; - } + cwd_start = 1; + } /* At least one VMS FTP server (TCPware V5.6-2) can switch to a UNIX emulation mode when given a UNIX-like directory @@ -643,10 +643,10 @@ Error in server response, closing control connection.\n")); Unlike the rest of this block, this particular behavior _is_ VMS-specific, so it gets its own VMS test. */ - if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL)) + if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL)) { cwd_end = 3; - DEBUGP (("Using extra \"CWD []\" step for VMS server.\n")); + DEBUGP (("Using extra \"CWD []\" step for VMS server.\n")); } else { @@ -656,22 +656,22 @@ Error in server response, closing control connection.\n")); /* 2004-09-20 SMS. */ /* Sorry about the deviant indenting. Laziness. */ - for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++) - { + for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++) + { switch (cwd_count) { case 0: - /* Step one (optional): Go to the initial directory, - exactly as reported by the server. - */ - targ = con->id; + /* Step one (optional): Go to the initial directory, + exactly as reported by the server. + */ + targ = con->id; break; case 1: - /* Step two: Go to the target directory. (Absolute or - relative will work now.) - */ - targ = target; + /* Step two: Go to the target directory. (Absolute or + relative will work now.) + */ + targ = target; break; case 2: @@ -684,7 +684,7 @@ Error in server response, closing control connection.\n")); default: /* Can't happen. */ assert (1); - } + } if (!opt.server_response) logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count, @@ -938,42 +938,42 @@ Error in server response, closing control connection.\n")); if (cmd & DO_RETR) { /* If we're in spider mode, don't really retrieve anything except - the directory listing and verify whether the given "file" exists. */ + the directory listing and verify whether the given "file" exists. */ if (opt.spider) { - bool exists = false; - uerr_t res; - struct fileinfo *f; - res = ftp_get_listing (u, con, &f); - /* Set the DO_RETR command flag again, because it gets unset when - calling ftp_get_listing() and would otherwise cause an assertion - failure earlier on when this function gets repeatedly called - (e.g., when recursing). */ - con->cmd |= DO_RETR; - if (res == RETROK) - { - while (f) - { - if (!strcmp (f->name, u->file)) - { - exists = true; - break; - } - f = f->next; - } + bool exists = false; + uerr_t res; + struct fileinfo *f; + res = ftp_get_listing (u, con, &f); + /* Set the DO_RETR command flag again, because it gets unset when + calling ftp_get_listing() and would otherwise cause an assertion + failure earlier on when this function gets repeatedly called + (e.g., when recursing). */ + con->cmd |= DO_RETR; + if (res == RETROK) + { + while (f) + { + if (!strcmp (f->name, u->file)) + { + exists = true; + break; + } + f = f->next; + } if (exists) { logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("File %s exists.\n"), quote (u->file)); } - else + else { - logputs (LOG_VERBOSE, "\n"); - logprintf (LOG_NOTQUIET, _("No such file %s.\n"), - quote (u->file)); - } - } + logputs (LOG_VERBOSE, "\n"); + logprintf (LOG_NOTQUIET, _("No such file %s.\n"), + quote (u->file)); + } + } fd_close (csock); con->csock = -1; fd_close (dtsock); @@ -1184,20 +1184,20 @@ Error in server response, closing control connection.\n")); else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct || opt.output_document || count > 0) { - if (opt.unlink && file_exists_p (con->target)) - { - int res = unlink (con->target); - if (res < 0) - { - logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, - strerror (errno)); - fd_close (csock); - con->csock = -1; - fd_close (dtsock); - fd_close (local_sock); - return UNLINKERR; - } - } + if (opt.unlink && file_exists_p (con->target)) + { + int res = unlink (con->target); + if (res < 0) + { + logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, + strerror (errno)); + fd_close (csock); + con->csock = -1; + fd_close (dtsock); + fd_close (local_sock); + return UNLINKERR; + } + } #ifdef __VMS int open_id; @@ -1367,18 +1367,20 @@ Error in server response, closing control connection.\n")); logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno)); else { - char *line; - /* The lines are being read with read_whole_line because of + char *line = NULL; + size_t bufsize = 0; + ssize_t len; + + /* The lines are being read with getline because of no-buffering on opt.lfile. */ - while ((line = read_whole_line (fp)) != NULL) + while ((len = getline (&line, &bufsize, fp)) > 0) { - char *p = strchr (line, '\0'); - while (p > line && (p[-1] == '\n' || p[-1] == '\r')) - *--p = '\0'; + while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) + line[--len] = '\0'; logprintf (LOG_ALWAYS, "%s\n", quotearg_style (escape_quoting_style, line)); - xfree (line); } + xfree (line); fclose (fp); } } /* con->cmd & DO_LIST && server_response */ diff --git a/src/init.c b/src/init.c index 0c418255..54a29198 100644 --- a/src/init.c +++ b/src/init.c @@ -574,7 +574,8 @@ bool run_wgetrc (const char *file) { FILE *fp; - char *line; + char *line = NULL; + size_t bufsize = 0; int ln; int errcnt = 0; @@ -586,7 +587,7 @@ run_wgetrc (const char *file) return true; /* not a fatal error */ } ln = 1; - while ((line = read_whole_line (fp)) != NULL) + while (getline (&line, &bufsize, fp) > 0) { char *com = NULL, *val = NULL; int comind; @@ -620,9 +621,9 @@ run_wgetrc (const char *file) } xfree_null (com); xfree_null (val); - xfree (line); ++ln; } + xfree (line); fclose (fp); return errcnt == 0; diff --git a/src/netrc.c b/src/netrc.c index 193d4f37..a31e0796 100644 --- a/src/netrc.c +++ b/src/netrc.c @@ -164,48 +164,6 @@ search_netrc (const char *host, const char **acc, const char **passwd, # define xrealloc realloc -/* Read a line from FP. The function reallocs the storage as needed - to accomodate for any length of the line. Reallocs are done - storage exponentially, doubling the storage after each overflow to - minimize the number of calls to realloc() and fgets(). The newline - character at the end of line is retained. - - After end-of-file is encountered without anything being read, NULL - is returned. NULL is also returned on error. To distinguish - between these two cases, use the stdio function ferror(). */ - -char * -read_whole_line (FILE *fp) -{ - int length = 0; - int bufsize = 81; - char *line = xmalloc (bufsize); - - while (fgets (line + length, bufsize - length, fp)) - { - length += strlen (line + length); - assert (length > 0); - if (line[length - 1] == '\n') - break; - /* fgets() guarantees to read the whole line, or to use up the - space we've given it. We can double the buffer - unconditionally. */ - bufsize <<= 1; - line = xrealloc (line, bufsize); - } - if (length == 0 || ferror (fp)) - { - xfree (line); - return NULL; - } - if (length + 1 < bufsize) - /* Relieve the memory from our exponential greediness. We say - `length + 1' because the terminating \0 is not included in - LENGTH. We don't need to zero-terminate the string ourselves, - though, because fgets() does that. */ - line = xrealloc (line, length + 1); - return line; -} #endif /* STANDALONE */ /* Maybe add NEWENTRY to the account information list, LIST. NEWENTRY is @@ -264,10 +222,11 @@ static acc_t * parse_netrc (const char *path) { FILE *fp; - char *line, *p, *tok; + char *line = NULL, *p, *tok; const char *premature_token; acc_t *current, *retval; int ln, qmark; + size_t bufsize = 0; /* The latest token we've seen in the file. */ enum @@ -290,7 +249,7 @@ parse_netrc (const char *path) premature_token = NULL; /* While there are lines in the file... */ - while ((line = read_whole_line (fp)) != NULL) + while (getline (&line, &bufsize, fp) > 0) { ln ++; @@ -423,10 +382,9 @@ parse_netrc (const char *path) exec_name, path, ln, tok); } } - - xfree (line); } + xfree (line); fclose (fp); /* Finalize the last machine entry we found. */ diff --git a/src/utils.c b/src/utils.c index 8817283d..f87853dc 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1118,56 +1118,6 @@ has_html_suffix_p (const char *fname) return false; } -/* Read a line from FP and return the pointer to freshly allocated - storage. The storage space is obtained through malloc() and should - be freed with free() when it is no longer needed. - - The length of the line is not limited, except by available memory. - The newline character at the end of line is retained. The line is - terminated with a zero character. - - After end-of-file is encountered without anything being read, NULL - is returned. NULL is also returned on error. To distinguish - between these two cases, use the stdio function ferror(). */ - -char * -read_whole_line (FILE *fp) -{ - int length = 0; - int bufsize = 82; - char *line = xmalloc (bufsize); - - while (fgets (line + length, bufsize - length, fp)) - { - length += strlen (line + length); - if (length == 0) - /* Possible for example when reading from a binary file where - a line begins with \0. */ - continue; - - if (line[length - 1] == '\n') - break; - - /* fgets() guarantees to read the whole line, or to use up the - space we've given it. We can double the buffer - unconditionally. */ - bufsize <<= 1; - line = xrealloc (line, bufsize); - } - if (length == 0 || ferror (fp)) - { - xfree (line); - return NULL; - } - if (length + 1 < bufsize) - /* Relieve the memory from our exponential greediness. We say - `length + 1' because the terminating \0 is not included in - LENGTH. We don't need to zero-terminate the string ourselves, - though, because fgets() does that. */ - line = xrealloc (line, length + 1); - return line; -} - /* Read FILE into memory. A pointer to `struct file_memory' are returned; use struct element `content' to access file contents, and the element `length' to know the file length. `content' is *not* diff --git a/src/utils.h b/src/utils.h index 67d8d25d..7c6f2ce2 100644 --- a/src/utils.h +++ b/src/utils.h @@ -98,7 +98,6 @@ bool has_wildcards_p (const char *); bool has_html_suffix_p (const char *); -char *read_whole_line (FILE *); struct file_memory *wget_read_file (const char *); void wget_read_file_free (struct file_memory *);