libopkg: store compressed package lists
[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         return trim_xstrdup(line + strlen(type) + 1);
39 }
40
41 /*
42  * Parse a comma separated string into an array.
43  */
44 char **
45 parse_list(const char *raw, unsigned int *count, const char sep, int skip_field)
46 {
47         char **depends = NULL;
48         const char *start, *end;
49         int line_count = 0;
50
51         /* skip past the "Field:" marker */
52         if (!skip_field) {
53         while (*raw && *raw != ':')
54                 raw++;
55         raw++;
56         }
57
58         if (line_is_blank(raw)) {
59                 *count = line_count;
60                 return NULL;
61         }
62
63         while (*raw) {
64                 depends = xrealloc(depends, sizeof(char *) * (line_count + 1));
65         
66                 while (isspace(*raw))
67                         raw++;
68
69                 start = raw;
70                 while (*raw != sep && *raw)
71                         raw++;
72                 end = raw;
73
74                 while (end > start && isspace(*end))
75                         end--;
76
77                 if (sep == ' ')
78                         end++;
79
80                 depends[line_count] = xstrndup(start, end-start);
81
82                 line_count++;
83                 if (*raw == sep)
84                     raw++;
85         }
86
87         *count = line_count;
88         return depends;
89 }
90
91 int
92 parse_from_stream_nomalloc(parse_line_t parse_line, void *item, FILE *fp, uint mask,
93                                                 char **buf0, size_t buf0len)
94 {
95         int ret, lineno;
96         char *buf, *nl;
97         size_t buflen;
98
99         lineno = 1;
100         ret = 0;
101
102         buflen = buf0len;
103         buf = *buf0;
104         buf[0] = '\0';
105
106         while (1) {
107                 if (fgets(buf, (int)buflen, fp) == NULL) {
108                         if (ferror(fp)) {
109                                 opkg_perror(ERROR, "fgets");
110                                 ret = -1;
111                         } else if (strlen(*buf0) == buf0len-1) {
112                                 opkg_msg(ERROR, "Missing new line character"
113                                                 " at end of file!\n");
114                                 parse_line(item, *buf0, mask);
115                         }
116                         break;
117                 }
118
119                 nl = strchr(buf, '\n');
120                 if (nl == NULL) {
121                         if (strlen(buf) < buflen-1) {
122                                 /*
123                                  * Line could be exactly buflen-1 long and
124                                  * missing a newline, but we won't know until
125                                  * fgets fails to read more data.
126                                  */
127                                 opkg_msg(ERROR, "Missing new line character"
128                                                 " at end of file!\n");
129                                 parse_line(item, *buf0, mask);
130                                 break;
131                         }
132                         if (buf0len >= EXCESSIVE_LINE_LEN) {
133                                 opkg_msg(ERROR, "Excessively long line at "
134                                         "%d. Corrupt file?\n",
135                                         lineno);
136                                 ret = -1;
137                                 break;
138                         }
139
140                         /*
141                          * Realloc and point buf past the data already read,
142                          * at the NULL terminator inserted by fgets.
143                          * |<--------------- buf0len ----------------->|
144                          * |                     |<------- buflen ---->|
145                          * |---------------------|---------------------|
146                          * buf0                   buf
147                          */
148                         buflen = buf0len +1;
149                         buf0len *= 2;
150                         *buf0 = xrealloc(*buf0, buf0len);
151                         buf = *buf0 + buflen -2;
152
153                         continue;
154                 }
155
156                 *nl = '\0';
157
158                 lineno++;
159
160                 if (parse_line(item, *buf0, mask))
161                         break;
162
163                 buf = *buf0;
164                 buflen = buf0len;
165                 buf[0] = '\0';
166         }
167
168         return ret;
169 }
170