diff options
Diffstat (limited to 'libopkg/parse_util.c')
-rw-r--r-- | libopkg/parse_util.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/libopkg/parse_util.c b/libopkg/parse_util.c index e01b124..538bb11 100644 --- a/libopkg/parse_util.c +++ b/libopkg/parse_util.c @@ -22,6 +22,7 @@ #include "libbb/libbb.h" #include "parse_util.h" +#include "pkg_parse.h" int is_field(const char *type, const char *line) @@ -86,3 +87,83 @@ parse_list(const char *raw, unsigned int *count, const char sep, int skip_field) *count = line_count; return depends; } + +int +parse_from_stream_nomalloc(pkg_t *pkg, FILE *fp, uint mask, + char **buf0, size_t buf0len) +{ + int ret, lineno; + char *buf, *nl; + size_t buflen; + + lineno = 1; + ret = 0; + + buflen = buf0len; + buf = *buf0; + buf[0] = '\0'; + + while (1) { + if (fgets(buf, (int)buflen, fp) == NULL) { + if (ferror(fp)) { + opkg_perror(ERROR, "fgets"); + ret = -1; + } else if (strlen(*buf0) == buf0len-1) { + opkg_msg(ERROR, "Missing new line character" + " at end of file!\n"); + pkg_parse_line(pkg, *buf0, mask); + } + break; + } + + nl = strchr(buf, '\n'); + if (nl == NULL) { + if (strlen(buf) < buflen-1) { + /* + * Line could be exactly buflen-1 long and + * missing a newline, but we won't know until + * fgets fails to read more data. + */ + opkg_msg(ERROR, "Missing new line character" + " at end of file!\n"); + pkg_parse_line(pkg, *buf0, mask); + break; + } + if (buf0len >= EXCESSIVE_LINE_LEN) { + opkg_msg(ERROR, "Excessively long line at " + "%d. Corrupt file?\n", + lineno); + ret = -1; + break; + } + + /* + * Realloc and point buf past the data already read, + * at the NULL terminator inserted by fgets. + * |<--------------- buf0len ----------------->| + * | |<------- buflen ---->| + * |---------------------|---------------------| + * buf0 buf + */ + buflen = buf0len +1; + buf0len *= 2; + *buf0 = xrealloc(*buf0, buf0len); + buf = *buf0 + buflen -2; + + continue; + } + + *nl = '\0'; + + lineno++; + + if (pkg_parse_line(pkg, *buf0, mask)) + break; + + buf = *buf0; + buflen = buf0len; + buf[0] = '\0'; + } + + return ret; +} |