libopkg: discard empty control file fields
[project/opkg-lede.git] / libopkg / parse_util.c
1 /* parse_util.c - the opkg package management system
2
3 Copyright (C) 2009 Ubiq Technologies <graham.gower@gmail.com>
4
5 Steven M. Ayer
6 Copyright (C) 2002 Compaq Computer Corporation
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17 */
18
19 #include <ctype.h>
20
21 #include "opkg_utils.h"
22 #include "libbb/libbb.h"
23
24 #include "parse_util.h"
25 #include "pkg_parse.h"
26
27 int
28 is_field(const char *type, const char *line)
29 {
30 if (!strncmp(line, type, strlen(type)))
31 return 1;
32 return 0;
33 }
34
35 char *
36 parse_simple(const char *type, const char *line)
37 {
38 char *field = trim_xstrdup(line + strlen(type) + 1);
39 if (strlen(field) == 0) {
40 free(field);
41 return NULL;
42 }
43 return field;
44 }
45
46 /*
47 * Parse a comma separated string into an array.
48 */
49 char **
50 parse_list(const char *raw, unsigned int *count, const char sep, int skip_field)
51 {
52 char **depends = NULL;
53 const char *start, *end;
54 int line_count = 0;
55
56 /* skip past the "Field:" marker */
57 if (!skip_field) {
58 while (*raw && *raw != ':')
59 raw++;
60 raw++;
61 }
62
63 if (line_is_blank(raw)) {
64 *count = line_count;
65 return NULL;
66 }
67
68 while (*raw) {
69 depends = xrealloc(depends, sizeof(char *) * (line_count + 1));
70
71 while (isspace(*raw))
72 raw++;
73
74 start = raw;
75 while (*raw != sep && *raw)
76 raw++;
77 end = raw;
78
79 while (end > start && isspace(*end))
80 end--;
81
82 if (sep == ' ')
83 end++;
84
85 depends[line_count] = xstrndup(start, end-start);
86
87 line_count++;
88 if (*raw == sep)
89 raw++;
90 }
91
92 *count = line_count;
93 return depends;
94 }
95
96 int
97 parse_from_stream_nomalloc(parse_line_t parse_line, void *item, FILE *fp, uint mask,
98 char **buf0, size_t buf0len)
99 {
100 int ret, lineno;
101 char *buf, *nl;
102 size_t buflen;
103
104 lineno = 1;
105 ret = 0;
106
107 buflen = buf0len;
108 buf = *buf0;
109 buf[0] = '\0';
110
111 while (1) {
112 if (fgets(buf, (int)buflen, fp) == NULL) {
113 if (ferror(fp)) {
114 opkg_perror(ERROR, "fgets");
115 ret = -1;
116 } else if (strlen(*buf0) == buf0len-1) {
117 opkg_msg(ERROR, "Missing new line character"
118 " at end of file!\n");
119 parse_line(item, *buf0, mask);
120 }
121 break;
122 }
123
124 nl = strchr(buf, '\n');
125 if (nl == NULL) {
126 if (strlen(buf) < buflen-1) {
127 /*
128 * Line could be exactly buflen-1 long and
129 * missing a newline, but we won't know until
130 * fgets fails to read more data.
131 */
132 opkg_msg(ERROR, "Missing new line character"
133 " at end of file!\n");
134 parse_line(item, *buf0, mask);
135 break;
136 }
137 if (buf0len >= EXCESSIVE_LINE_LEN) {
138 opkg_msg(ERROR, "Excessively long line at "
139 "%d. Corrupt file?\n",
140 lineno);
141 ret = -1;
142 break;
143 }
144
145 /*
146 * Realloc and point buf past the data already read,
147 * at the NULL terminator inserted by fgets.
148 * |<--------------- buf0len ----------------->|
149 * | |<------- buflen ---->|
150 * |---------------------|---------------------|
151 * buf0 buf
152 */
153 buflen = buf0len +1;
154 buf0len *= 2;
155 *buf0 = xrealloc(*buf0, buf0len);
156 buf = *buf0 + buflen -2;
157
158 continue;
159 }
160
161 *nl = '\0';
162
163 lineno++;
164
165 if (parse_line(item, *buf0, mask))
166 break;
167
168 buf = *buf0;
169 buflen = buf0len;
170 buf[0] = '\0';
171 }
172
173 return ret;
174 }
175