X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=libbb%2Ffgets_str.c;h=1a7f2e9e090b3731da1bd674028c098d2b31c1da;hb=fb957125d8aa83c9df6e54292327983a51ee7ffd;hp=7d41d72f1d63c4ada9e670f720b43167fb461dee;hpb=1bf25f030777a83ed498914ad65ba3d44b8b3fdc;p=oweals%2Fbusybox.git diff --git a/libbb/fgets_str.c b/libbb/fgets_str.c index 7d41d72f1..1a7f2e9e0 100644 --- a/libbb/fgets_str.c +++ b/libbb/fgets_str.c @@ -1,31 +1,15 @@ +/* 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 source tree. */ +#include "libbb.h" - -#include -#include -#include - -/* - * 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 +17,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 +42,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 || linebuf[0] == '\n') { - 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); +}