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"
26 int isGenericFieldType(char * type, char * line)
28 if(!strncmp(line, type, strlen(type)))
33 char * parseGenericFieldType(char * type, char * raw)
35 char * field_value = raw + (strlen(type) + 1);
36 return trim_alloc(field_value);
39 void parseStatus(pkg_t *pkg, char * raw)
41 char sw_str[64], sf_str[64], ss_str[64];
43 sscanf(raw, "Status: %s %s %s", sw_str, sf_str, ss_str);
44 pkg->state_want = pkg_state_want_from_str(sw_str);
45 pkg->state_flag = pkg_state_flag_from_str(sf_str);
46 pkg->state_status = pkg_state_status_from_str(ss_str);
49 char ** parseDependsString(char * raw, int * depends_count)
51 char ** depends = NULL;
53 char buff[2048], * dest;
55 while(raw && *raw && !isspace(*raw)) {
59 if(line_is_blank(raw)){
60 *depends_count = line_count;
64 depends = (char **)realloc(depends, sizeof(char *) * (line_count + 1));
66 while(isspace(*raw)) raw++;
69 while((*raw != ',') && *raw)
73 depends[line_count] = trim_alloc(buff);
74 if(depends[line_count] ==NULL)
80 *depends_count = line_count;
84 void parseConffiles(pkg_t * pkg, char * raw)
86 char file_name[1048], md5sum[1048]; /* please tell me there aren't any longer that 1k */
88 if(!strncmp(raw, "Conffiles:", 10))
89 raw += strlen("Conffiles:");
91 while(*raw && (sscanf(raw, "%s%s", file_name, md5sum) == 2)){
92 conffile_list_append(&pkg->conffiles, file_name, md5sum);
93 /* fprintf(stderr, "%s %s ", file_name, md5sum);*/
94 while (*raw && isspace(*raw)) {
97 raw += strlen(file_name);
98 while (*raw && isspace(*raw)) {
101 raw += strlen(md5sum);
105 int parseVersion(pkg_t *pkg, char *raw)
107 char *colon, *eepochcolon;
112 fprintf(stderr, "%s: ERROR: version string is empty", __FUNCTION__);
116 if (strncmp(raw, "Version:", 8) == 0) {
119 while (*raw && isspace(*raw)) {
123 colon= strchr(raw,':');
125 epoch= strtoul(raw,&eepochcolon,10);
126 if (colon != eepochcolon) {
127 fprintf(stderr, "%s: ERROR: epoch in version is not number", __FUNCTION__);
131 fprintf(stderr, "%s: ERROR: nothing after colon in version number", __FUNCTION__);
144 pkg->version= malloc(strlen(raw)+1);
145 if ( pkg->version == NULL ) {
146 fprintf(stderr, "%s: out of memory \n", __FUNCTION__);
149 strcpy(pkg->version, raw);
152 hyphen= strrchr(pkg->version,'-');
156 pkg->revision = hyphen;
163 /* This code is needed to insert in first position the keyword for the aligning bug */
165 int alterProvidesLine(char *raw, char *temp)
170 fprintf(stderr, "%s: ERROR: Provides string is empty", __FUNCTION__);
174 if ( temp == NULL ) {
175 fprintf(stderr, "%s: out of memory \n", __FUNCTION__);
179 if (strncmp(raw, "Provides:", 9) == 0) {
182 while (*raw && isspace(*raw)) {
186 snprintf ( temp, 35, "Provides: opkg_internal_use_only, "); /* First part of the line */
188 strncat( temp, raw++, 1);
194 /* Some random thoughts from Carl:
196 This function could be considerably simplified if we just kept
197 an array of all the generic string-valued field names, and looped
198 through those looking for a match. Also, these fields could perhaps
199 be stored in the package as an array as well, (or, probably better,
200 as an nv_pair_list_t).
202 Fields which require special parsing or storage, (such as Depends:
203 and Status:) could be handled as they are now.
205 /* XXX: FEATURE: The Suggests: field needs to be changed from a string
206 to a dependency list. And, since we already have
207 Depends/Pre-Depends and need to add Conflicts, Recommends, and
208 Enhances, perhaps we could generalize all of these and save some
211 int pkg_parse_raw(pkg_t *pkg, char ***raw, pkg_src_t *src, pkg_dest_t *dest)
213 int reading_conffiles, reading_description;
214 int pkg_false_provides=1;
221 reading_conffiles = reading_description = 0;
223 for (lines = *raw; *lines; lines++) {
224 /* fprintf(stderr, "PARSING %s\n", *lines);*/
227 if(isGenericFieldType("Package:", *lines))
228 pkg->name = parseGenericFieldType("Package", *lines);
229 else if(isGenericFieldType("Priority:", *lines))
230 pkg->priority = parseGenericFieldType("Priority", *lines);
231 else if(isGenericFieldType("Provides", *lines)){
232 /* Here we add the internal_use to align the off by one problem between provides_str and provides */
233 provide = (char * ) malloc(strlen(*lines)+ 35 ); /* Preparing the space for the new opkg_internal_use_only */
234 if ( alterProvidesLine(*lines,provide) ){
237 pkg->provides_str = parseDependsString( provide, &pkg->provides_count);
238 /* Let's try to hack a bit here.
239 The idea is that if a package has no Provides, we would add one generic, to permit the check of dependencies
240 in alot of other places. We will remove it before writing down the status database */
241 pkg_false_provides=0;
244 else if(isGenericFieldType("Pre-Depends", *lines))
245 pkg->pre_depends_str = parseDependsString(*lines, &pkg->pre_depends_count);
249 if(isGenericFieldType("Architecture:", *lines))
250 pkg->architecture = parseGenericFieldType("Architecture", *lines);
251 else if(isGenericFieldType("Auto-Installed:", *lines)) {
252 char *auto_installed_value;
253 auto_installed_value = parseGenericFieldType("Auto-Installed:", *lines);
254 if (strcmp(auto_installed_value, "yes") == 0) {
255 pkg->auto_installed = 1;
257 free(auto_installed_value);
262 if(isGenericFieldType("Filename:", *lines))
263 pkg->filename = parseGenericFieldType("Filename", *lines);
267 if(isGenericFieldType("Section:", *lines))
268 pkg->section = parseGenericFieldType("Section", *lines);
269 else if(isGenericFieldType("Size:", *lines))
270 pkg->size = parseGenericFieldType("Size", *lines);
271 else if(isGenericFieldType("Source:", *lines))
272 pkg->source = parseGenericFieldType("Source", *lines);
273 else if(isGenericFieldType("Status", *lines))
274 parseStatus(pkg, *lines);
275 else if(isGenericFieldType("Suggests", *lines))
276 pkg->suggests_str = parseDependsString(*lines, &pkg->suggests_count);
280 if(isGenericFieldType("Tags:", *lines))
281 pkg->tags = parseGenericFieldType("Tags", *lines);
285 if(isGenericFieldType("MD5sum:", *lines))
286 pkg->md5sum = parseGenericFieldType("MD5sum", *lines);
287 /* The old opkg wrote out status files with the wrong case for MD5sum,
288 let's parse it either way */
289 else if(isGenericFieldType("MD5Sum:", *lines))
290 pkg->md5sum = parseGenericFieldType("MD5Sum", *lines);
291 else if(isGenericFieldType("Maintainer", *lines))
292 pkg->maintainer = parseGenericFieldType("Maintainer", *lines);
296 if(isGenericFieldType("Installed-Size:", *lines))
297 pkg->installed_size = parseGenericFieldType("Installed-Size", *lines);
298 else if(isGenericFieldType("Installed-Time:", *lines)) {
299 char *time_str = parseGenericFieldType("Installed-Time", *lines);
300 pkg->installed_time = strtoul(time_str, NULL, 0);
306 if(isGenericFieldType("Essential:", *lines)) {
307 char *essential_value;
308 essential_value = parseGenericFieldType("Essential", *lines);
309 if (strcmp(essential_value, "yes") == 0) {
312 free(essential_value);
317 if(isGenericFieldType("Version", *lines))
318 parseVersion(pkg, *lines);
322 if(isGenericFieldType("Conffiles", *lines)){
323 parseConffiles(pkg, *lines);
324 reading_conffiles = 1;
326 else if(isGenericFieldType("Conflicts", *lines))
327 pkg->conflicts_str = parseDependsString(*lines, &pkg->conflicts_count);
331 if(isGenericFieldType("Description", *lines)) {
332 pkg->description = parseGenericFieldType("Description", *lines);
333 reading_conffiles = 0;
334 reading_description = 1;
336 else if(isGenericFieldType("Depends", *lines))
337 pkg->depends_str = parseDependsString(*lines, &pkg->depends_count);
341 if(isGenericFieldType("Recommends", *lines))
342 pkg->recommends_str = parseDependsString(*lines, &pkg->recommends_count);
343 else if(isGenericFieldType("Replaces", *lines))
344 pkg->replaces_str = parseDependsString(*lines, &pkg->replaces_count);
349 if(reading_description) {
350 /* we already know it's not blank, so the rest of description */
351 pkg->description = realloc(pkg->description,
352 strlen(pkg->description)
353 + 1 + strlen(*lines) + 1);
354 strcat(pkg->description, "\n");
355 strcat(pkg->description, (*lines));
357 else if(reading_conffiles)
358 parseConffiles(pkg, *lines);
363 if(line_is_blank(*lines)) {
372 /* If the ipk has not a Provides line, we insert our false line */
373 if ( pkg_false_provides==1)
375 pkg->provides_count = 1;
376 pkg->provides_str = malloc (sizeof (char*));
377 pkg->provides_str[0] = strdup ("opkg_internal_use_only");
387 int pkg_valorize_other_field(pkg_t *pkg, char ***raw)
391 for (lines = *raw; *lines; lines++) {
392 if(isGenericFieldType("Essential:", *lines)) {
393 char *essential_value;
394 essential_value = parseGenericFieldType("Essential", *lines);
395 if (strcmp(essential_value, "yes") == 0) {
398 free(essential_value);