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 = xrealloc(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= xcalloc(1, strlen(raw)+1);
146 strcpy(pkg->version, raw);
149 hyphen= strrchr(pkg->version,'-');
153 pkg->revision = hyphen;
160 /* This code is needed to insert in first position the keyword for the aligning bug */
162 int alterProvidesLine(char *raw, char *temp)
167 fprintf(stderr, "%s: ERROR: Provides string is empty", __FUNCTION__);
171 if ( temp == NULL ) {
172 fprintf(stderr, "%s: out of memory \n", __FUNCTION__);
176 if (strncmp(raw, "Provides:", 9) == 0) {
179 while (*raw && isspace(*raw)) {
183 snprintf ( temp, 35, "Provides: opkg_internal_use_only, "); /* First part of the line */
185 strncat( temp, raw++, 1);
191 /* Some random thoughts from Carl:
193 This function could be considerably simplified if we just kept
194 an array of all the generic string-valued field names, and looped
195 through those looking for a match. Also, these fields could perhaps
196 be stored in the package as an array as well, (or, probably better,
197 as an nv_pair_list_t).
199 Fields which require special parsing or storage, (such as Depends:
200 and Status:) could be handled as they are now.
202 /* XXX: FEATURE: The Suggests: field needs to be changed from a string
203 to a dependency list. And, since we already have
204 Depends/Pre-Depends and need to add Conflicts, Recommends, and
205 Enhances, perhaps we could generalize all of these and save some
208 int pkg_parse_raw(pkg_t *pkg, char ***raw, pkg_src_t *src, pkg_dest_t *dest)
210 int reading_conffiles, reading_description;
211 int pkg_false_provides=1;
218 reading_conffiles = reading_description = 0;
220 for (lines = *raw; *lines; lines++) {
221 /* fprintf(stderr, "PARSING %s\n", *lines);*/
224 if(isGenericFieldType("Package:", *lines))
225 pkg->name = parseGenericFieldType("Package", *lines);
226 else if(isGenericFieldType("Priority:", *lines))
227 pkg->priority = parseGenericFieldType("Priority", *lines);
228 else if(isGenericFieldType("Provides", *lines)){
229 /* Here we add the internal_use to align the off by one problem between provides_str and provides */
230 provide = xcalloc(1, strlen(*lines)+ 35 ); /* Preparing the space for the new opkg_internal_use_only */
231 if ( alterProvidesLine(*lines,provide) ){
234 pkg->provides_str = parseDependsString( provide, &pkg->provides_count);
235 /* Let's try to hack a bit here.
236 The idea is that if a package has no Provides, we would add one generic, to permit the check of dependencies
237 in alot of other places. We will remove it before writing down the status database */
238 pkg_false_provides=0;
241 else if(isGenericFieldType("Pre-Depends", *lines))
242 pkg->pre_depends_str = parseDependsString(*lines, &pkg->pre_depends_count);
246 if(isGenericFieldType("Architecture:", *lines))
247 pkg->architecture = parseGenericFieldType("Architecture", *lines);
248 else if(isGenericFieldType("Auto-Installed:", *lines)) {
249 char *auto_installed_value;
250 auto_installed_value = parseGenericFieldType("Auto-Installed:", *lines);
251 if (strcmp(auto_installed_value, "yes") == 0) {
252 pkg->auto_installed = 1;
254 free(auto_installed_value);
259 if(isGenericFieldType("Filename:", *lines))
260 pkg->filename = parseGenericFieldType("Filename", *lines);
264 if(isGenericFieldType("Section:", *lines))
265 pkg->section = parseGenericFieldType("Section", *lines);
267 else if(isGenericFieldType("SHA256sum:", *lines))
268 pkg->sha256sum = parseGenericFieldType("SHA256sum", *lines);
270 else if(isGenericFieldType("Size:", *lines))
271 pkg->size = parseGenericFieldType("Size", *lines);
272 else if(isGenericFieldType("Source:", *lines))
273 pkg->source = parseGenericFieldType("Source", *lines);
274 else if(isGenericFieldType("Status", *lines))
275 parseStatus(pkg, *lines);
276 else if(isGenericFieldType("Suggests", *lines))
277 pkg->suggests_str = parseDependsString(*lines, &pkg->suggests_count);
281 if(isGenericFieldType("Tags:", *lines))
282 pkg->tags = parseGenericFieldType("Tags", *lines);
286 if(isGenericFieldType("MD5sum:", *lines))
287 pkg->md5sum = parseGenericFieldType("MD5sum", *lines);
288 /* The old opkg wrote out status files with the wrong case for MD5sum,
289 let's parse it either way */
290 else if(isGenericFieldType("MD5Sum:", *lines))
291 pkg->md5sum = parseGenericFieldType("MD5Sum", *lines);
292 else if(isGenericFieldType("Maintainer", *lines))
293 pkg->maintainer = parseGenericFieldType("Maintainer", *lines);
297 if(isGenericFieldType("Installed-Size:", *lines))
298 pkg->installed_size = parseGenericFieldType("Installed-Size", *lines);
299 else if(isGenericFieldType("Installed-Time:", *lines)) {
300 char *time_str = parseGenericFieldType("Installed-Time", *lines);
301 pkg->installed_time = strtoul(time_str, NULL, 0);
307 if(isGenericFieldType("Essential:", *lines)) {
308 char *essential_value;
309 essential_value = parseGenericFieldType("Essential", *lines);
310 if (strcmp(essential_value, "yes") == 0) {
313 free(essential_value);
318 if(isGenericFieldType("Version", *lines))
319 parseVersion(pkg, *lines);
323 if(isGenericFieldType("Conffiles", *lines)){
324 parseConffiles(pkg, *lines);
325 reading_conffiles = 1;
327 else if(isGenericFieldType("Conflicts", *lines))
328 pkg->conflicts_str = parseDependsString(*lines, &pkg->conflicts_count);
332 if(isGenericFieldType("Description", *lines)) {
333 pkg->description = parseGenericFieldType("Description", *lines);
334 reading_conffiles = 0;
335 reading_description = 1;
337 else if(isGenericFieldType("Depends", *lines))
338 pkg->depends_str = parseDependsString(*lines, &pkg->depends_count);
342 if(isGenericFieldType("Recommends", *lines))
343 pkg->recommends_str = parseDependsString(*lines, &pkg->recommends_count);
344 else if(isGenericFieldType("Replaces", *lines))
345 pkg->replaces_str = parseDependsString(*lines, &pkg->replaces_count);
350 if(reading_description) {
351 /* we already know it's not blank, so the rest of description */
352 pkg->description = xrealloc(pkg->description,
353 strlen(pkg->description)
354 + 1 + strlen(*lines) + 1);
355 strcat(pkg->description, "\n");
356 strcat(pkg->description, (*lines));
358 else if(reading_conffiles)
359 parseConffiles(pkg, *lines);
364 if(line_is_blank(*lines)) {
373 /* If the opk has not a Provides line, we insert our false line */
374 if ( pkg_false_provides==1)
376 pkg->provides_count = 1;
377 pkg->provides_str = xcalloc(1, sizeof (char*));
378 pkg->provides_str[0] = xstrdup("opkg_internal_use_only");
388 int pkg_valorize_other_field(pkg_t *pkg, char ***raw)
392 for (lines = *raw; *lines; lines++) {
393 if(isGenericFieldType("Essential:", *lines)) {
394 char *essential_value;
395 essential_value = parseGenericFieldType("Essential", *lines);
396 if (strcmp(essential_value, "yes") == 0) {
399 free(essential_value);