diff options
Diffstat (limited to 'release/src/router/busybox/libbb/fgets_str.c')
-rw-r--r-- | release/src/router/busybox/libbb/fgets_str.c | 84 |
1 files changed, 53 insertions, 31 deletions
diff --git a/release/src/router/busybox/libbb/fgets_str.c b/release/src/router/busybox/libbb/fgets_str.c index 33d8d00c..3fe61cdc 100644 --- a/release/src/router/busybox/libbb/fgets_str.c +++ b/release/src/router/busybox/libbb/fgets_str.c @@ -1,31 +1,16 @@ +/* vi: set sw=4 ts=4: */ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Utility routines. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. + * Copyright (C) many different people. + * If you wrote this, please acknowledge your work. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ +#include "libbb.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* - * Continue reading from file until the terminating string is encountered. - * Return data as string. - * e.g. fgets_str(file, "\n"); will read till end of file - */ - -char *fgets_str(FILE *file, const char *terminating_string) +static char *xmalloc_fgets_internal(FILE *file, const char *terminating_string, int chop_off, size_t *maxsz_p) { char *linebuf = NULL; const int term_length = strlen(terminating_string); @@ -33,16 +18,24 @@ char *fgets_str(FILE *file, const char *terminating_string) int linebufsz = 0; int idx = 0; int ch; + size_t maxsz = *maxsz_p; while (1) { ch = fgetc(file); if (ch == EOF) { + if (idx == 0) + return linebuf; /* NULL */ break; } - /* grow the line buffer as necessary */ - while (idx > linebufsz - 2) { - linebuf = realloc(linebuf, linebufsz += 1000); /* GROWBY */ + if (idx >= linebufsz) { + linebufsz += 200; + linebuf = xrealloc(linebuf, linebufsz); + if (idx >= maxsz) { + linebuf[idx] = ch; + idx++; + break; + } } linebuf[idx] = ch; @@ -50,15 +43,44 @@ char *fgets_str(FILE *file, const char *terminating_string) /* Check for terminating string */ end_string_offset = idx - term_length; - if ((end_string_offset > 0) && (memcmp(&linebuf[end_string_offset], terminating_string, term_length) == 0)) { - idx -= term_length; + if (end_string_offset >= 0 + && memcmp(&linebuf[end_string_offset], terminating_string, term_length) == 0 + ) { + if (chop_off) + idx -= term_length; break; } } - if (idx == 0) { - return NULL; - } + /* Grow/shrink *first*, then store NUL */ + linebuf = xrealloc(linebuf, idx + 1); linebuf[idx] = '\0'; - return(linebuf); + *maxsz_p = idx; + return linebuf; +} + +/* Read up to TERMINATING_STRING from FILE and return it, + * including terminating string. + * Non-terminated string can be returned if EOF is reached. + * Return NULL if EOF is reached immediately. */ +char* FAST_FUNC xmalloc_fgets_str(FILE *file, const char *terminating_string) +{ + size_t maxsz = INT_MAX - 4095; + return xmalloc_fgets_internal(file, terminating_string, 0, &maxsz); } +char* FAST_FUNC xmalloc_fgets_str_len(FILE *file, const char *terminating_string, size_t *maxsz_p) +{ + size_t maxsz; + + if (!maxsz_p) { + maxsz = INT_MAX - 4095; + maxsz_p = &maxsz; + } + return xmalloc_fgets_internal(file, terminating_string, 0, maxsz_p); +} + +char* FAST_FUNC xmalloc_fgetline_str(FILE *file, const char *terminating_string) +{ + size_t maxsz = INT_MAX - 4095; + return xmalloc_fgets_internal(file, terminating_string, 1, &maxsz); +} |