summaryrefslogtreecommitdiffstats
path: root/libopkg/parse_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'libopkg/parse_util.c')
-rw-r--r--libopkg/parse_util.c81
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;
+}