From: Roy Marples Date: Wed, 5 Nov 2008 13:57:54 +0000 (+0000) Subject: get_line now uses a single buffer, strips leading space and skips comments. This... X-Git-Tag: v5.0.0~192 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e1caa8dbade9d653dec2172b5c052f1dbeaebb22;p=thirdparty%2Fdhcpcd.git get_line now uses a single buffer, strips leading space and skips comments. This reduces malloc usage slightly and gives a cleaner API at the expense of a slight bss increase. --- diff --git a/common.c b/common.c index bfd0b9c7..802b42be 100644 --- a/common.c +++ b/common.c @@ -51,31 +51,64 @@ # define _PATH_DEVNULL "/dev/null" #endif -int clock_monotonic = 0; +int clock_monotonic; +static char *lbuf; +static size_t lbuf_len; + +#ifdef DEBUG_MEMORY +static void +free_lbuf(void) +{ + free(lbuf); +} +#endif /* Handy routine to read very long lines in text files. - * This means we read the whole line and avoid any nasty buffer overflows. */ -ssize_t -get_line(char **line, size_t *len, FILE *fp) + * This means we read the whole line and avoid any nasty buffer overflows. + * We strip leading space and avoid comment lines, making the code that calls + * us smaller. + * As we don't use threads, this API is clean too. */ +char * +get_line(FILE * restrict fp) { - char *p; - size_t last = 0; + char *p, *e; + size_t last; + +again: + if (feof(fp)) + return NULL; + +#ifdef DEBUG_MEMORY + if (!lbuf) + atexit(free_lbuf); +#endif - while(!feof(fp)) { - if (*line == NULL || last != 0) { - *len += BUFSIZ; - *line = xrealloc(*line, *len); + last = 0; + do { + if (!lbuf || last != 0) { + lbuf_len += BUFSIZ; + lbuf = xrealloc(lbuf, lbuf_len); } - p = *line + last; + p = lbuf + last; memset(p, 0, BUFSIZ); fgets(p, BUFSIZ, fp); last += strlen(p); - if (last && (*line)[last - 1] == '\n') { - (*line)[last - 1] = '\0'; + if (last && lbuf[last - 1] == '\n') { + lbuf[last - 1] = '\0'; break; } + } while(!feof(fp)); + if (!last) + return NULL; + + e = p + last - 1; + for (p = lbuf; p < e; p++) { + if (*p != ' ' && *p != '\t') + break; } - return last; + if (p == e || *p == '#' || *p == ';') + goto again; + return p; } /* Simple hack to return a random number without arc4random */ diff --git a/common.h b/common.h index 453d6b77..c5879452 100644 --- a/common.h +++ b/common.h @@ -86,7 +86,7 @@ int closefrom(int); int set_cloexec(int); int set_nonblock(int); -ssize_t get_line(char **, size_t *, FILE *); +char *get_line(FILE * restrict); extern int clock_monotonic; int get_monotonic(struct timeval *); time_t uptime(void); diff --git a/duid.c b/duid.c index 8b19550a..dddb3b94 100644 --- a/duid.c +++ b/duid.c @@ -47,30 +47,23 @@ get_duid(unsigned char *duid, const struct interface *iface) time_t t; int x = 0; unsigned char *p = duid; - size_t len = 0, l = 0; - char *buffer = NULL, *line, *option; + size_t len = 0; + char *line; /* If we already have a DUID then use it as it's never supposed * to change once we have one even if the interfaces do */ if ((f = fopen(DUID, "r"))) { - while ((get_line(&buffer, &len, f))) { - line = buffer; - while ((option = strsep(&line, " \t"))) - if (*option != '\0') - break; - if (!option || *option == '\0' || *option == '#') - continue; - l = hwaddr_aton(NULL, option); - if (l && l <= DUID_LEN) { - hwaddr_aton(duid, option); + while ((line = get_line(f))) { + len = hwaddr_aton(NULL, line); + if (len && len <= DUID_LEN) { + hwaddr_aton(duid, line); break; } - l = 0; + len = 0; } fclose(f); - free(buffer); - if (l) - return l; + if (len) + return len; } else { if (errno != ENOENT) return 0; diff --git a/if-linux.c b/if-linux.c index bbbc5493..188a9af5 100644 --- a/if-linux.c +++ b/if-linux.c @@ -431,18 +431,15 @@ struct interface * discover_interfaces(int argc, char * const *argv) { FILE *f; - char *buffer = NULL, *p; - size_t len = 0, ln = 0, n; + char *p; + size_t ln = 0, n; int i; struct interface *ifs = NULL, *ifp, *ifl; if ((f = fopen("/proc/net/dev", "r"))) { - while (get_line(&buffer, &len, f)) { + while (p = get_line(f)) { if (++ln < 2) continue; - p = buffer; - while (isspace((unsigned int)*p)) - p++; n = strcspn(p, ": \t"); p[n]= '\0'; ifl = NULL; @@ -479,7 +476,6 @@ discover_interfaces(int argc, char * const *argv) } } fclose(f); - free(buffer); } return ifs; } diff --git a/if-options.c b/if-options.c index 3965119d..24bf5ad3 100644 --- a/if-options.c +++ b/if-options.c @@ -586,8 +586,7 @@ read_config(const char *file, const char *ifname) { struct if_options *ifo; FILE *f; - size_t len = 0; - char *line, *option, *p, *buffer = NULL; + char *line, *option, *p; int skip = 0; /* Seed our default options */ @@ -612,18 +611,8 @@ read_config(const char *file, const char *ifname) if (!f) return ifo; - while ((get_line(&buffer, &len, f))) { - line = buffer; - while ((option = strsep(&line, " \t"))) - if (*option != '\0') - break; - if (!option || *option == '\0' || *option == '#') - continue; - /* Trim leading whitespace */ - if (line) { - while (*line != '\0' && (*line == ' ' || *line == '\t')) - line++; - } + while ((line = get_line(f))) { + option = strsep(&line, " \t"); /* Trim trailing whitespace */ if (line && *line) { p = line + strlen(line) - 1; @@ -646,7 +635,6 @@ read_config(const char *file, const char *ifname) break; } } - free(buffer); fclose(f); /* Terminate the encapsulated options */