| 1 | --- a/libopkg/parse_util.c |
| 2 | +++ b/libopkg/parse_util.c |
| 3 | @@ -22,6 +22,7 @@ |
| 4 | #include "libbb/libbb.h" |
| 5 | |
| 6 | #include "parse_util.h" |
| 7 | +#include "pkg_parse.h" |
| 8 | |
| 9 | int |
| 10 | is_field(const char *type, const char *line) |
| 11 | @@ -86,3 +87,84 @@ parse_list(const char *raw, unsigned int |
| 12 | *count = line_count; |
| 13 | return depends; |
| 14 | } |
| 15 | + |
| 16 | +int |
| 17 | +parse_from_stream_nomalloc(parse_line_t parse_line, void *item, FILE *fp, uint mask, |
| 18 | + char **buf0, size_t buf0len) |
| 19 | +{ |
| 20 | + int ret, lineno; |
| 21 | + char *buf, *nl; |
| 22 | + size_t buflen; |
| 23 | + |
| 24 | + lineno = 1; |
| 25 | + ret = 0; |
| 26 | + |
| 27 | + buflen = buf0len; |
| 28 | + buf = *buf0; |
| 29 | + buf[0] = '\0'; |
| 30 | + |
| 31 | + while (1) { |
| 32 | + if (fgets(buf, (int)buflen, fp) == NULL) { |
| 33 | + if (ferror(fp)) { |
| 34 | + opkg_perror(ERROR, "fgets"); |
| 35 | + ret = -1; |
| 36 | + } else if (strlen(*buf0) == buf0len-1) { |
| 37 | + opkg_msg(ERROR, "Missing new line character" |
| 38 | + " at end of file!\n"); |
| 39 | + parse_line(item, *buf0, mask); |
| 40 | + } |
| 41 | + break; |
| 42 | + } |
| 43 | + |
| 44 | + nl = strchr(buf, '\n'); |
| 45 | + if (nl == NULL) { |
| 46 | + if (strlen(buf) < buflen-1) { |
| 47 | + /* |
| 48 | + * Line could be exactly buflen-1 long and |
| 49 | + * missing a newline, but we won't know until |
| 50 | + * fgets fails to read more data. |
| 51 | + */ |
| 52 | + opkg_msg(ERROR, "Missing new line character" |
| 53 | + " at end of file!\n"); |
| 54 | + parse_line(item, *buf0, mask); |
| 55 | + break; |
| 56 | + } |
| 57 | + if (buf0len >= EXCESSIVE_LINE_LEN) { |
| 58 | + opkg_msg(ERROR, "Excessively long line at " |
| 59 | + "%d. Corrupt file?\n", |
| 60 | + lineno); |
| 61 | + ret = -1; |
| 62 | + break; |
| 63 | + } |
| 64 | + |
| 65 | + /* |
| 66 | + * Realloc and point buf past the data already read, |
| 67 | + * at the NULL terminator inserted by fgets. |
| 68 | + * |<--------------- buf0len ----------------->| |
| 69 | + * | |<------- buflen ---->| |
| 70 | + * |---------------------|---------------------| |
| 71 | + * buf0 buf |
| 72 | + */ |
| 73 | + buflen = buf0len +1; |
| 74 | + buf0len *= 2; |
| 75 | + *buf0 = xrealloc(*buf0, buf0len); |
| 76 | + buf = *buf0 + buflen -2; |
| 77 | + |
| 78 | + continue; |
| 79 | + } |
| 80 | + |
| 81 | + *nl = '\0'; |
| 82 | + |
| 83 | + lineno++; |
| 84 | + |
| 85 | + if (parse_line(item, *buf0, mask)) |
| 86 | + break; |
| 87 | + |
| 88 | + buf = *buf0; |
| 89 | + buflen = buf0len; |
| 90 | + buf[0] = '\0'; |
| 91 | + } |
| 92 | + |
| 93 | + return ret; |
| 94 | +} |
| 95 | + |
| 96 | --- a/libopkg/parse_util.h |
| 97 | +++ b/libopkg/parse_util.h |
| 98 | @@ -22,4 +22,8 @@ int is_field(const char *type, const cha |
| 99 | char *parse_simple(const char *type, const char *line); |
| 100 | char **parse_list(const char *raw, unsigned int *count, const char sep, int skip_field); |
| 101 | |
| 102 | +typedef int (*parse_line_t)(void *, const char *, uint); |
| 103 | +int parse_from_stream_nomalloc(parse_line_t parse_line, void *item, FILE *fp, uint mask, |
| 104 | + char **buf0, size_t buf0len); |
| 105 | + |
| 106 | #endif |
| 107 | --- a/libopkg/pkg_hash.c |
| 108 | +++ b/libopkg/pkg_hash.c |
| 109 | @@ -23,6 +23,7 @@ |
| 110 | #include "opkg_message.h" |
| 111 | #include "pkg_vec.h" |
| 112 | #include "pkg_hash.h" |
| 113 | +#include "parse_util.h" |
| 114 | #include "pkg_parse.h" |
| 115 | #include "opkg_utils.h" |
| 116 | #include "sprintf_alloc.h" |
| 117 | @@ -119,8 +120,14 @@ pkg_hash_add_from_file(const char *file_ |
| 118 | pkg->src = src; |
| 119 | pkg->dest = dest; |
| 120 | |
| 121 | - ret = pkg_parse_from_stream_nomalloc(pkg, fp, 0, |
| 122 | + ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, 0, |
| 123 | &buf, len); |
| 124 | + |
| 125 | + if (pkg->name == NULL) { |
| 126 | + /* probably just a blank line */ |
| 127 | + ret = 1; |
| 128 | + } |
| 129 | + |
| 130 | if (ret) { |
| 131 | pkg_deinit (pkg); |
| 132 | free(pkg); |
| 133 | --- a/libopkg/pkg_parse.c |
| 134 | +++ b/libopkg/pkg_parse.c |
| 135 | @@ -104,9 +104,11 @@ get_arch_priority(const char *arch) |
| 136 | return 0; |
| 137 | } |
| 138 | |
| 139 | -static int |
| 140 | -pkg_parse_line(pkg_t *pkg, const char *line, uint mask) |
| 141 | +int |
| 142 | +pkg_parse_line(void *ptr, const char *line, uint mask) |
| 143 | { |
| 144 | + pkg_t *pkg = (pkg_t *) ptr; |
| 145 | + |
| 146 | /* these flags are a bit hackish... */ |
| 147 | static int reading_conffiles = 0, reading_description = 0; |
| 148 | int ret = 0; |
| 149 | @@ -266,91 +268,6 @@ dont_reset_flags: |
| 150 | } |
| 151 | |
| 152 | int |
| 153 | -pkg_parse_from_stream_nomalloc(pkg_t *pkg, FILE *fp, uint mask, |
| 154 | - char **buf0, size_t buf0len) |
| 155 | -{ |
| 156 | - int ret, lineno; |
| 157 | - char *buf, *nl; |
| 158 | - size_t buflen; |
| 159 | - |
| 160 | - lineno = 1; |
| 161 | - ret = 0; |
| 162 | - |
| 163 | - buflen = buf0len; |
| 164 | - buf = *buf0; |
| 165 | - buf[0] = '\0'; |
| 166 | - |
| 167 | - while (1) { |
| 168 | - if (fgets(buf, (int)buflen, fp) == NULL) { |
| 169 | - if (ferror(fp)) { |
| 170 | - opkg_perror(ERROR, "fgets"); |
| 171 | - ret = -1; |
| 172 | - } else if (strlen(*buf0) == buf0len-1) { |
| 173 | - opkg_msg(ERROR, "Missing new line character" |
| 174 | - " at end of file!\n"); |
| 175 | - pkg_parse_line(pkg, *buf0, mask); |
| 176 | - } |
| 177 | - break; |
| 178 | - } |
| 179 | - |
| 180 | - nl = strchr(buf, '\n'); |
| 181 | - if (nl == NULL) { |
| 182 | - if (strlen(buf) < buflen-1) { |
| 183 | - /* |
| 184 | - * Line could be exactly buflen-1 long and |
| 185 | - * missing a newline, but we won't know until |
| 186 | - * fgets fails to read more data. |
| 187 | - */ |
| 188 | - opkg_msg(ERROR, "Missing new line character" |
| 189 | - " at end of file!\n"); |
| 190 | - pkg_parse_line(pkg, *buf0, mask); |
| 191 | - break; |
| 192 | - } |
| 193 | - if (buf0len >= EXCESSIVE_LINE_LEN) { |
| 194 | - opkg_msg(ERROR, "Excessively long line at " |
| 195 | - "%d. Corrupt file?\n", |
| 196 | - lineno); |
| 197 | - ret = -1; |
| 198 | - break; |
| 199 | - } |
| 200 | - |
| 201 | - /* |
| 202 | - * Realloc and point buf past the data already read, |
| 203 | - * at the NULL terminator inserted by fgets. |
| 204 | - * |<--------------- buf0len ----------------->| |
| 205 | - * | |<------- buflen ---->| |
| 206 | - * |---------------------|---------------------| |
| 207 | - * buf0 buf |
| 208 | - */ |
| 209 | - buflen = buf0len +1; |
| 210 | - buf0len *= 2; |
| 211 | - *buf0 = xrealloc(*buf0, buf0len); |
| 212 | - buf = *buf0 + buflen -2; |
| 213 | - |
| 214 | - continue; |
| 215 | - } |
| 216 | - |
| 217 | - *nl = '\0'; |
| 218 | - |
| 219 | - lineno++; |
| 220 | - |
| 221 | - if (pkg_parse_line(pkg, *buf0, mask)) |
| 222 | - break; |
| 223 | - |
| 224 | - buf = *buf0; |
| 225 | - buflen = buf0len; |
| 226 | - buf[0] = '\0'; |
| 227 | - } |
| 228 | - |
| 229 | - if (pkg->name == NULL) { |
| 230 | - /* probably just a blank line */ |
| 231 | - ret = 1; |
| 232 | - } |
| 233 | - |
| 234 | - return ret; |
| 235 | -} |
| 236 | - |
| 237 | -int |
| 238 | pkg_parse_from_stream(pkg_t *pkg, FILE *fp, uint mask) |
| 239 | { |
| 240 | int ret; |
| 241 | @@ -358,8 +275,13 @@ pkg_parse_from_stream(pkg_t *pkg, FILE * |
| 242 | const size_t len = 4096; |
| 243 | |
| 244 | buf = xmalloc(len); |
| 245 | - ret = pkg_parse_from_stream_nomalloc(pkg, fp, mask, &buf, len); |
| 246 | + ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, mask, &buf, len); |
| 247 | free(buf); |
| 248 | |
| 249 | + if (pkg->name == NULL) { |
| 250 | + /* probably just a blank line */ |
| 251 | + ret = 1; |
| 252 | + } |
| 253 | + |
| 254 | return ret; |
| 255 | } |
| 256 | --- a/libopkg/pkg_parse.h |
| 257 | +++ b/libopkg/pkg_parse.h |
| 258 | @@ -18,10 +18,11 @@ |
| 259 | #ifndef PKG_PARSE_H |
| 260 | #define PKG_PARSE_H |
| 261 | |
| 262 | +#include "pkg.h" |
| 263 | + |
| 264 | int parse_version(pkg_t *pkg, const char *raw); |
| 265 | int pkg_parse_from_stream(pkg_t *pkg, FILE *fp, uint mask); |
| 266 | -int pkg_parse_from_stream_nomalloc(pkg_t *pkg, FILE *fp, uint mask, |
| 267 | - char **buf0, size_t buf0len); |
| 268 | +int pkg_parse_line(void *ptr, const char *line, uint mask); |
| 269 | |
| 270 | #define EXCESSIVE_LINE_LEN (4096 << 8) |
| 271 | |
| 272 | --- a/libopkg/release_parse.c |
| 273 | +++ b/libopkg/release_parse.c |
| 274 | @@ -23,8 +23,10 @@ |
| 275 | #include "parse_util.h" |
| 276 | |
| 277 | static int |
| 278 | -release_parse_line(release_t *release, const char *line) |
| 279 | +release_parse_line(void *ptr, const char *line, uint mask) |
| 280 | { |
| 281 | + release_t *release = (release_t *) ptr; |
| 282 | + |
| 283 | int ret = 0; |
| 284 | unsigned int count = 0; |
| 285 | char **list = 0; |
| 286 | @@ -111,25 +113,14 @@ dont_reset_flags: |
| 287 | int |
| 288 | release_parse_from_stream(release_t *release, FILE *fp) |
| 289 | { |
| 290 | - int ret = 0; |
| 291 | - char *buf = NULL; |
| 292 | - size_t buflen, nread; |
| 293 | - |
| 294 | - nread = getline(&buf, &buflen, fp); |
| 295 | - while ( nread != -1 ) { |
| 296 | - if (buf[nread-1] == '\n') buf[nread-1] = '\0'; |
| 297 | - if (release_parse_line(release, buf)) |
| 298 | - opkg_msg(DEBUG, "Failed to parse release line for %s:\n\t%s\n", |
| 299 | - release->name, buf); |
| 300 | - nread = getline(&buf, &buflen, fp); |
| 301 | - } |
| 302 | - |
| 303 | - if (!feof(fp)) { |
| 304 | - opkg_perror(ERROR, "Problems reading Release file for %sd\n", release->name); |
| 305 | - ret = -1; |
| 306 | - } |
| 307 | + int ret; |
| 308 | + char *buf; |
| 309 | + const size_t len = 4096; |
| 310 | |
| 311 | + buf = xmalloc(len); |
| 312 | + ret = parse_from_stream_nomalloc(release_parse_line, release, fp, 0, &buf, len); |
| 313 | free(buf); |
| 314 | + |
| 315 | return ret; |
| 316 | } |
| 317 | |
| 318 | |