1 /* pkg_parse.c - the opkg package management system
5 Copyright (C) 2002 Compaq Computer Corporation
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
23 #include "opkg_utils.h"
24 #include "pkg_parse.h"
25 #include "libbb/libbb.h"
27 int isGenericFieldType(char * type, char * line)
29 if(!strncmp(line, type, strlen(type)))
34 char * parseGenericFieldType(char * type, char * raw)
36 char * field_value = raw + (strlen(type) + 1);
37 return trim_alloc(field_value);
40 void parseStatus(pkg_t *pkg, char * raw)
42 char sw_str[64], sf_str[64], ss_str[64];
44 sscanf(raw, "Status: %s %s %s", sw_str, sf_str, ss_str);
45 pkg->state_want = pkg_state_want_from_str(sw_str);
46 pkg->state_flag = pkg_state_flag_from_str(sf_str);
47 pkg->state_status = pkg_state_status_from_str(ss_str);
50 char ** parseDependsString(char * raw, int * depends_count)
52 char ** depends = NULL;
54 char buff[2048], * dest;
56 while(raw && *raw && !isspace(*raw)) {
60 if(line_is_blank(raw)){
61 *depends_count = line_count;
65 depends = (char **)realloc(depends, sizeof(char *) * (line_count + 1));
67 while(isspace(*raw)) raw++;
70 while((*raw != ',') && *raw)
74 depends[line_count] = trim_alloc(buff);
75 if(depends[line_count] ==NULL)
81 *depends_count = line_count;
85 void parseConffiles(pkg_t * pkg, char * raw)
87 char file_name[1048], md5sum[1048]; /* please tell me there aren't any longer that 1k */
89 if(!strncmp(raw, "Conffiles:", 10))
90 raw += strlen("Conffiles:");
92 while(*raw && (sscanf(raw, "%s%s", file_name, md5sum) == 2)){
93 conffile_list_append(&pkg->conffiles, file_name, md5sum);
94 /* fprintf(stderr, "%s %s ", file_name, md5sum);*/
95 while (*raw && isspace(*raw)) {
98 raw += strlen(file_name);
99 while (*raw && isspace(*raw)) {
102 raw += strlen(md5sum);
106 int parseVersion(pkg_t *pkg, char *raw)
108 char *colon, *eepochcolon;
113 fprintf(stderr, "%s: ERROR: version string is empty", __FUNCTION__);
117 if (strncmp(raw, "Version:", 8) == 0) {
120 while (*raw && isspace(*raw)) {
124 colon= strchr(raw,':');
126 epoch= strtoul(raw,&eepochcolon,10);
127 if (colon != eepochcolon) {
128 fprintf(stderr, "%s: ERROR: epoch in version is not number", __FUNCTION__);
132 fprintf(stderr, "%s: ERROR: nothing after colon in version number", __FUNCTION__);
145 pkg->version= calloc(1, strlen(raw)+1);
146 if ( pkg->version == NULL ) {
147 fprintf(stderr, "%s: out of memory \n", __FUNCTION__);
150 strcpy(pkg->version, raw);
153 hyphen= strrchr(pkg->version,'-');
157 pkg->revision = hyphen;
164 /* This code is needed to insert in first position the keyword for the aligning bug */
166 int alterProvidesLine(char *raw, char *temp)
171 fprintf(stderr, "%s: ERROR: Provides string is empty", __FUNCTION__);
175 if ( temp == NULL ) {
176 fprintf(stderr, "%s: out of memory \n", __FUNCTION__);
180 if (strncmp(raw, "Provides:", 9) == 0) {
183 while (*raw && isspace(*raw)) {
187 snprintf ( temp, 35, "Provides: opkg_internal_use_only, "); /* First part of the line */
189 strncat( temp, raw++, 1);
195 /* Some random thoughts from Carl:
197 This function could be considerably simplified if we just kept
198 an array of all the generic string-valued field names, and looped
199 through those looking for a match. Also, these fields could perhaps
200 be stored in the package as an array as well, (or, probably better,
201 as an nv_pair_list_t).
203 Fields which require special parsing or storage, (such as Depends:
204 and Status:) could be handled as they are now.
206 /* XXX: FEATURE: The Suggests: field needs to be changed from a string
207 to a dependency list. And, since we already have
208 Depends/Pre-Depends and need to add Conflicts, Recommends, and
209 Enhances, perhaps we could generalize all of these and save some
212 int pkg_parse_raw(pkg_t *pkg, char ***raw, pkg_src_t *src, pkg_dest_t *dest)
214 int reading_conffiles, reading_description;
215 int pkg_false_provides=1;
222 reading_conffiles = reading_description = 0;
224 for (lines = *raw; *lines; lines++) {
225 /* fprintf(stderr, "PARSING %s\n", *lines);*/
228 if(isGenericFieldType("Package:", *lines))
229 pkg->name = parseGenericFieldType("Package", *lines);
230 else if(isGenericFieldType("Priority:", *lines))
231 pkg->priority = parseGenericFieldType("Priority", *lines);
232 else if(isGenericFieldType("Provides", *lines)){
233 /* Here we add the internal_use to align the off by one problem between provides_str and provides */
234 provide = (char * ) calloc(1, strlen(*lines)+ 35 ); /* Preparing the space for the new opkg_internal_use_only */
235 if ( alterProvidesLine(*lines,provide) ){
238 pkg->provides_str = parseDependsString( provide, &pkg->provides_count);
239 /* Let's try to hack a bit here.
240 The idea is that if a package has no Provides, we would add one generic, to permit the check of dependencies
241 in alot of other places. We will remove it before writing down the status database */
242 pkg_false_provides=0;
245 else if(isGenericFieldType("Pre-Depends", *lines))
246 pkg->pre_depends_str = parseDependsString(*lines, &pkg->pre_depends_count);
250 if(isGenericFieldType("Architecture:", *lines))
251 pkg->architecture = parseGenericFieldType("Architecture", *lines);
252 else if(isGenericFieldType("Auto-Installed:", *lines)) {
253 char *auto_installed_value;
254 auto_installed_value = parseGenericFieldType("Auto-Installed:", *lines);
255 if (strcmp(auto_installed_value, "yes") == 0) {
256 pkg->auto_installed = 1;
258 free(auto_installed_value);
263 if(isGenericFieldType("Filename:", *lines))
264 pkg->filename = parseGenericFieldType("Filename", *lines);
268 if(isGenericFieldType("Section:", *lines))
269 pkg->section = parseGenericFieldType("Section", *lines);
271 else if(isGenericFieldType("SHA256sum:", *lines))
272 pkg->sha256sum = parseGenericFieldType("SHA256sum", *lines);
274 else if(isGenericFieldType("Size:", *lines))
275 pkg->size = parseGenericFieldType("Size", *lines);
276 else if(isGenericFieldType("Source:", *lines))
277 pkg->source = parseGenericFieldType("Source", *lines);
278 else if(isGenericFieldType("Status", *lines))
279 parseStatus(pkg, *lines);
280 else if(isGenericFieldType("Suggests", *lines))
281 pkg->suggests_str = parseDependsString(*lines, &pkg->suggests_count);
285 if(isGenericFieldType("Tags:", *lines))
286 pkg->tags = parseGenericFieldType("Tags", *lines);
290 if(isGenericFieldType("MD5sum:", *lines))
291 pkg->md5sum = parseGenericFieldType("MD5sum", *lines);
292 /* The old opkg wrote out status files with the wrong case for MD5sum,
293 let's parse it either way */
294 else if(isGenericFieldType("MD5Sum:", *lines))
295 pkg->md5sum = parseGenericFieldType("MD5Sum", *lines);
296 else if(isGenericFieldType("Maintainer", *lines))
297 pkg->maintainer = parseGenericFieldType("Maintainer", *lines);
301 if(isGenericFieldType("Installed-Size:", *lines))
302 pkg->installed_size = parseGenericFieldType("Installed-Size", *lines);
303 else if(isGenericFieldType("Installed-Time:", *lines)) {
304 char *time_str = parseGenericFieldType("Installed-Time", *lines);
305 pkg->installed_time = strtoul(time_str, NULL, 0);
311 if(isGenericFieldType("Essential:", *lines)) {
312 char *essential_value;
313 essential_value = parseGenericFieldType("Essential", *lines);
314 if (strcmp(essential_value, "yes") == 0) {
317 free(essential_value);
322 if(isGenericFieldType("Version", *lines))
323 parseVersion(pkg, *lines);
327 if(isGenericFieldType("Conffiles", *lines)){
328 parseConffiles(pkg, *lines);
329 reading_conffiles = 1;
331 else if(isGenericFieldType("Conflicts", *lines))
332 pkg->conflicts_str = parseDependsString(*lines, &pkg->conflicts_count);
336 if(isGenericFieldType("Description", *lines)) {
337 pkg->description = parseGenericFieldType("Description", *lines);
338 reading_conffiles = 0;
339 reading_description = 1;
341 else if(isGenericFieldType("Depends", *lines))
342 pkg->depends_str = parseDependsString(*lines, &pkg->depends_count);
346 if(isGenericFieldType("Recommends", *lines))
347 pkg->recommends_str = parseDependsString(*lines, &pkg->recommends_count);
348 else if(isGenericFieldType("Replaces", *lines))
349 pkg->replaces_str = parseDependsString(*lines, &pkg->replaces_count);
354 if(reading_description) {
355 /* we already know it's not blank, so the rest of description */
356 pkg->description = realloc(pkg->description,
357 strlen(pkg->description)
358 + 1 + strlen(*lines) + 1);
359 strcat(pkg->description, "\n");
360 strcat(pkg->description, (*lines));
362 else if(reading_conffiles)
363 parseConffiles(pkg, *lines);
368 if(line_is_blank(*lines)) {
377 /* If the opk has not a Provides line, we insert our false line */
378 if ( pkg_false_provides==1)
380 pkg->provides_count = 1;
381 pkg->provides_str = calloc (1, sizeof (char*));
382 pkg->provides_str[0] = xstrdup("opkg_internal_use_only");
392 int pkg_valorize_other_field(pkg_t *pkg, char ***raw)
396 for (lines = *raw; *lines; lines++) {
397 if(isGenericFieldType("Essential:", *lines)) {
398 char *essential_value;
399 essential_value = parseGenericFieldType("Essential", *lines);
400 if (strcmp(essential_value, "yes") == 0) {
403 free(essential_value);