X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=libopkg%2Fparse_util.c;h=4d453afa2323e8f20c85f8857e7c9aa3ca1c2b0a;hb=4283ab3c37ebe4deb670dd049857b020c8794552;hp=e01b12427efee895f38a173e4360346864af7e4f;hpb=449b23e18889d916075d37527cb21834976babb2;p=oweals%2Fopkg-lede.git diff --git a/libopkg/parse_util.c b/libopkg/parse_util.c index e01b124..4d453af 100644 --- a/libopkg/parse_util.c +++ b/libopkg/parse_util.c @@ -22,26 +22,30 @@ #include "libbb/libbb.h" #include "parse_util.h" +#include "pkg_parse.h" -int -is_field(const char *type, const char *line) +int is_field(const char *type, const char *line) { if (!strncmp(line, type, strlen(type))) return 1; return 0; } -char * -parse_simple(const char *type, const char *line) +char *parse_simple(const char *type, const char *line) { - return trim_xstrdup(line + strlen(type) + 1); + char *field = trim_xstrdup(line + strlen(type) + 1); + if (strlen(field) == 0) { + free(field); + return NULL; + } + return field; } /* * Parse a comma separated string into an array. */ -char ** -parse_list(const char *raw, unsigned int *count, const char sep, int skip_field) +char **parse_list(const char *raw, unsigned int *count, const char sep, + int skip_field) { char **depends = NULL; const char *start, *end; @@ -49,9 +53,9 @@ parse_list(const char *raw, unsigned int *count, const char sep, int skip_field) /* skip past the "Field:" marker */ if (!skip_field) { - while (*raw && *raw != ':') + while (*raw && *raw != ':') + raw++; raw++; - raw++; } if (line_is_blank(raw)) { @@ -61,7 +65,7 @@ parse_list(const char *raw, unsigned int *count, const char sep, int skip_field) while (*raw) { depends = xrealloc(depends, sizeof(char *) * (line_count + 1)); - + while (isspace(*raw)) raw++; @@ -76,13 +80,92 @@ parse_list(const char *raw, unsigned int *count, const char sep, int skip_field) if (sep == ' ') end++; - depends[line_count] = xstrndup(start, end-start); + depends[line_count] = xstrndup(start, end - start); - line_count++; + line_count++; if (*raw == sep) - raw++; + raw++; } *count = line_count; return depends; } + +int +parse_from_stream_nomalloc(parse_line_t parse_line, void *item, 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"); + parse_line(item, *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"); + parse_line(item, *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 (parse_line(item, *buf0, mask)) + break; + + buf = *buf0; + buflen = buf0len; + buf[0] = '\0'; + } + + return ret; +}