libopkg: discard empty control file fields
[oweals/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