[opkg] fixing typo & incompatible part to gcc 4.3.2
[project/opkg-lede.git] / libopkg / pkg.c
1 /* pkg.c - the opkg package management system
2
3 Carl D. Worth
4
5 Copyright (C) 2001 University of Southern California
6
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.
11
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.
16 */
17
18 #include "includes.h"
19 #include <ctype.h>
20 #include <string.h>
21 #include <errno.h>
22
23 #include "pkg.h"
24
25 #include "pkg_parse.h"
26 #include "pkg_extract.h"
27 #include "opkg_message.h"
28 #include "opkg_utils.h"
29
30 #include "sprintf_alloc.h"
31 #include "file_util.h"
32 #include "str_util.h"
33 #include "xsystem.h"
34 #include "opkg_conf.h"
35
36 typedef struct enum_map enum_map_t;
37 struct enum_map
38 {
39 int value;
40 char *str;
41 };
42
43 static const enum_map_t pkg_state_want_map[] = {
44 { SW_UNKNOWN, "unknown"},
45 { SW_INSTALL, "install"},
46 { SW_DEINSTALL, "deinstall"},
47 { SW_PURGE, "purge"}
48 };
49
50 static const enum_map_t pkg_state_flag_map[] = {
51 { SF_OK, "ok"},
52 { SF_REINSTREQ, "reinstreq"},
53 { SF_HOLD, "hold"},
54 { SF_REPLACE, "replace"},
55 { SF_NOPRUNE, "noprune"},
56 { SF_PREFER, "prefer"},
57 { SF_OBSOLETE, "obsolete"},
58 { SF_USER, "user"},
59 };
60
61 static const enum_map_t pkg_state_status_map[] = {
62 { SS_NOT_INSTALLED, "not-installed" },
63 { SS_UNPACKED, "unpacked" },
64 { SS_HALF_CONFIGURED, "half-configured" },
65 { SS_INSTALLED, "installed" },
66 { SS_HALF_INSTALLED, "half-installed" },
67 { SS_CONFIG_FILES, "config-files" },
68 { SS_POST_INST_FAILED, "post-inst-failed" },
69 { SS_REMOVAL_FAILED, "removal-failed" }
70 };
71
72 static int verrevcmp(const char *val, const char *ref);
73
74
75 pkg_t *pkg_new(void)
76 {
77 pkg_t *pkg;
78
79 pkg = malloc(sizeof(pkg_t));
80 if (pkg == NULL) {
81 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
82 return NULL;
83 }
84
85 pkg_init(pkg);
86
87 return pkg;
88 }
89
90 int pkg_init(pkg_t *pkg)
91 {
92 memset(pkg, 0, sizeof(pkg_t));
93 pkg->name = NULL;
94 pkg->epoch = 0;
95 pkg->version = NULL;
96 pkg->revision = NULL;
97 pkg->dest = NULL;
98 pkg->src = NULL;
99 pkg->architecture = NULL;
100 pkg->maintainer = NULL;
101 pkg->section = NULL;
102 pkg->description = NULL;
103 pkg->state_want = SW_UNKNOWN;
104 pkg->state_flag = SF_OK;
105 pkg->state_status = SS_NOT_INSTALLED;
106 pkg->depends_str = NULL;
107 pkg->provides_str = NULL;
108 pkg->depends_count = 0;
109 pkg->depends = NULL;
110 pkg->suggests_str = NULL;
111 pkg->recommends_str = NULL;
112 pkg->suggests_count = 0;
113 pkg->recommends_count = 0;
114
115 /* Abhaya: added init for conflicts fields */
116 pkg->conflicts = NULL;
117 pkg->conflicts_count = 0;
118
119 /* added for replaces. Jamey 7/23/2002 */
120 pkg->replaces = NULL;
121 pkg->replaces_count = 0;
122
123 pkg->pre_depends_count = 0;
124 pkg->pre_depends_str = NULL;
125 pkg->provides_count = 0;
126 pkg->provides = NULL;
127 pkg->filename = NULL;
128 pkg->local_filename = NULL;
129 pkg->tmp_unpack_dir = NULL;
130 pkg->md5sum = NULL;
131 pkg->size = NULL;
132 pkg->installed_size = NULL;
133 pkg->priority = NULL;
134 pkg->source = NULL;
135 conffile_list_init(&pkg->conffiles);
136 pkg->installed_files = NULL;
137 pkg->installed_files_ref_cnt = 0;
138 pkg->essential = 0;
139 pkg->provided_by_hand = 0;
140
141 return 0;
142 }
143
144 void compound_depend_deinit (compound_depend_t *depends)
145 {
146 int i;
147 for (i = 0; i < depends->possibility_count; i++)
148 {
149 depend_t *d;
150 d = depends->possibilities[i];
151 free (d->version);
152 free (d);
153 }
154 free (depends->possibilities);
155 }
156
157 void pkg_deinit(pkg_t *pkg)
158 {
159 int i;
160
161 free(pkg->name);
162 pkg->name = NULL;
163 pkg->epoch = 0;
164 free(pkg->version);
165 pkg->version = NULL;
166 /* revision shares storage with version, so
167 don't free */
168 pkg->revision = NULL;
169 /* owned by opkg_conf_t */
170 pkg->dest = NULL;
171 /* owned by opkg_conf_t */
172 pkg->src = NULL;
173 free(pkg->architecture);
174 pkg->architecture = NULL;
175 free(pkg->maintainer);
176 pkg->maintainer = NULL;
177 free(pkg->section);
178 pkg->section = NULL;
179 free(pkg->description);
180 pkg->description = NULL;
181 pkg->state_want = SW_UNKNOWN;
182 pkg->state_flag = SF_OK;
183 pkg->state_status = SS_NOT_INSTALLED;
184
185 //for (i = 0; i < pkg->replaces_count; i++)
186 free (pkg->replaces);
187 pkg->replaces = NULL;
188
189 for (i = 0; i < pkg->depends_count; i++)
190 free (pkg->depends_str[i]);
191 free(pkg->depends_str);
192 pkg->depends_str = NULL;
193
194 for (i = 0; i < pkg->provides_count; i++)
195 free (pkg->provides_str[i]);
196 free(pkg->provides_str);
197 pkg->provides_str = NULL;
198
199 for (i = 0; i < pkg->conflicts_count; i++)
200 free (pkg->conflicts_str[i]);
201 free(pkg->conflicts_str);
202 pkg->conflicts_str = NULL;
203
204 for (i = 0; i < pkg->replaces_count; i++)
205 free (pkg->replaces_str[i]);
206 free(pkg->replaces_str);
207 pkg->replaces_str = NULL;
208
209 for (i = 0; i < pkg->recommends_count; i++)
210 free (pkg->recommends_str[i]);
211 free(pkg->recommends_str);
212 pkg->recommends_str = NULL;
213
214 for (i = 0; i < pkg->suggests_count; i++)
215 free (pkg->suggests_str[i]);
216 free(pkg->suggests_str);
217 pkg->suggests_str = NULL;
218
219 if (pkg->depends)
220 {
221 int count = pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count;
222 int x;
223
224 for (x = 0; x < count; x++)
225 compound_depend_deinit (&pkg->depends[x]);
226 free (pkg->depends);
227 }
228
229 if (pkg->conflicts)
230 {
231 int x;
232 for (x = 0; x < pkg->conflicts_count; x++)
233 compound_depend_deinit (&pkg->conflicts[x]);
234 free (pkg->conflicts);
235 }
236
237 free (pkg->provides);
238
239 pkg->pre_depends_count = 0;
240 free(pkg->pre_depends_str);
241 pkg->pre_depends_str = NULL;
242 pkg->provides_count = 0;
243 free(pkg->filename);
244 pkg->filename = NULL;
245 free(pkg->local_filename);
246 pkg->local_filename = NULL;
247 /* CLEANUP: It'd be nice to pullin the cleanup function from
248 opkg_install.c here. See comment in
249 opkg_install.c:cleanup_temporary_files */
250 free(pkg->tmp_unpack_dir);
251 pkg->tmp_unpack_dir = NULL;
252 free(pkg->md5sum);
253 pkg->md5sum = NULL;
254 free(pkg->size);
255 pkg->size = NULL;
256 free(pkg->installed_size);
257 pkg->installed_size = NULL;
258 free(pkg->priority);
259 pkg->priority = NULL;
260 free(pkg->source);
261 pkg->source = NULL;
262 conffile_list_deinit(&pkg->conffiles);
263 /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
264 since if they are calling deinit, they should know. Maybe do an
265 assertion here instead? */
266 pkg->installed_files_ref_cnt = 1;
267 pkg_free_installed_files(pkg);
268 pkg->essential = 0;
269 free (pkg->tags);
270 pkg->tags = NULL;
271 }
272
273 int pkg_init_from_file(pkg_t *pkg, const char *filename)
274 {
275 int err;
276 char **raw;
277 FILE *control_file;
278
279 err = pkg_init(pkg);
280 if (err) { return err; }
281
282 pkg->local_filename = strdup(filename);
283
284 control_file = tmpfile();
285 err = pkg_extract_control_file_to_stream(pkg, control_file);
286 if (err) { return err; }
287
288 rewind(control_file);
289 raw = read_raw_pkgs_from_stream(control_file);
290 pkg_parse_raw(pkg, &raw, NULL, NULL);
291
292 fclose(control_file);
293
294 return 0;
295 }
296
297 /* Merge any new information in newpkg into oldpkg */
298 /* XXX: CLEANUP: This function shouldn't actually modify anything in
299 newpkg, but should leave it usable. This rework is so that
300 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
301 /*
302 * uh, i thought that i had originally written this so that it took
303 * two pkgs and returned a new one? we can do that again... -sma
304 */
305 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
306 {
307 if (oldpkg == newpkg) {
308 return 0;
309 }
310
311 if (!oldpkg->src)
312 oldpkg->src = newpkg->src;
313 if (!oldpkg->dest)
314 oldpkg->dest = newpkg->dest;
315 if (!oldpkg->architecture)
316 oldpkg->architecture = str_dup_safe(newpkg->architecture);
317 if (!oldpkg->arch_priority)
318 oldpkg->arch_priority = newpkg->arch_priority;
319 if (!oldpkg->section)
320 oldpkg->section = str_dup_safe(newpkg->section);
321 if(!oldpkg->maintainer)
322 oldpkg->maintainer = str_dup_safe(newpkg->maintainer);
323 if(!oldpkg->description)
324 oldpkg->description = str_dup_safe(newpkg->description);
325 if (set_status) {
326 /* merge the state_flags from the new package */
327 oldpkg->state_want = newpkg->state_want;
328 oldpkg->state_status = newpkg->state_status;
329 oldpkg->state_flag = newpkg->state_flag;
330 } else {
331 if (oldpkg->state_want == SW_UNKNOWN)
332 oldpkg->state_want = newpkg->state_want;
333 if (oldpkg->state_status == SS_NOT_INSTALLED)
334 oldpkg->state_status = newpkg->state_status;
335 oldpkg->state_flag |= newpkg->state_flag;
336 }
337
338 if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
339 oldpkg->depends_str = newpkg->depends_str;
340 newpkg->depends_str = NULL;
341 oldpkg->depends_count = newpkg->depends_count;
342 newpkg->depends_count = 0;
343
344 oldpkg->depends = newpkg->depends;
345 newpkg->depends = NULL;
346
347 oldpkg->pre_depends_str = newpkg->pre_depends_str;
348 newpkg->pre_depends_str = NULL;
349 oldpkg->pre_depends_count = newpkg->pre_depends_count;
350 newpkg->pre_depends_count = 0;
351
352 oldpkg->recommends_str = newpkg->recommends_str;
353 newpkg->recommends_str = NULL;
354 oldpkg->recommends_count = newpkg->recommends_count;
355 newpkg->recommends_count = 0;
356
357 oldpkg->suggests_str = newpkg->suggests_str;
358 newpkg->suggests_str = NULL;
359 oldpkg->suggests_count = newpkg->suggests_count;
360 newpkg->suggests_count = 0;
361 }
362
363 if (!oldpkg->provides_str) {
364 oldpkg->provides_str = newpkg->provides_str;
365 newpkg->provides_str = NULL;
366 oldpkg->provides_count = newpkg->provides_count;
367 newpkg->provides_count = 0;
368
369 oldpkg->provides = newpkg->provides;
370 newpkg->provides = NULL;
371 }
372
373 if (!oldpkg->conflicts_str) {
374 oldpkg->conflicts_str = newpkg->conflicts_str;
375 newpkg->conflicts_str = NULL;
376 oldpkg->conflicts_count = newpkg->conflicts_count;
377 newpkg->conflicts_count = 0;
378
379 oldpkg->conflicts = newpkg->conflicts;
380 newpkg->conflicts = NULL;
381 }
382
383 if (!oldpkg->replaces_str) {
384 oldpkg->replaces_str = newpkg->replaces_str;
385 newpkg->replaces_str = NULL;
386 oldpkg->replaces_count = newpkg->replaces_count;
387 newpkg->replaces_count = 0;
388
389 oldpkg->replaces = newpkg->replaces;
390 newpkg->replaces = NULL;
391 }
392
393 if (!oldpkg->filename)
394 oldpkg->filename = str_dup_safe(newpkg->filename);
395 if (0)
396 fprintf(stdout, "pkg=%s old local_filename=%s new local_filename=%s\n",
397 oldpkg->name, oldpkg->local_filename, newpkg->local_filename);
398 if (!oldpkg->local_filename)
399 oldpkg->local_filename = str_dup_safe(newpkg->local_filename);
400 if (!oldpkg->tmp_unpack_dir)
401 oldpkg->tmp_unpack_dir = str_dup_safe(newpkg->tmp_unpack_dir);
402 if (!oldpkg->md5sum)
403 oldpkg->md5sum = str_dup_safe(newpkg->md5sum);
404 if (!oldpkg->size)
405 oldpkg->size = str_dup_safe(newpkg->size);
406 if (!oldpkg->installed_size)
407 oldpkg->installed_size = str_dup_safe(newpkg->installed_size);
408 if (!oldpkg->priority)
409 oldpkg->priority = str_dup_safe(newpkg->priority);
410 if (!oldpkg->source)
411 oldpkg->source = str_dup_safe(newpkg->source);
412 if (oldpkg->conffiles.head == NULL){
413 oldpkg->conffiles = newpkg->conffiles;
414 conffile_list_init(&newpkg->conffiles);
415 }
416 if (!oldpkg->installed_files){
417 oldpkg->installed_files = newpkg->installed_files;
418 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
419 newpkg->installed_files = NULL;
420 }
421 if (!oldpkg->essential)
422 oldpkg->essential = newpkg->essential;
423
424 return 0;
425 }
426
427 abstract_pkg_t *abstract_pkg_new(void)
428 {
429 abstract_pkg_t * ab_pkg;
430
431 ab_pkg = malloc(sizeof(abstract_pkg_t));
432
433 if (ab_pkg == NULL) {
434 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
435 return NULL;
436 }
437
438 if ( abstract_pkg_init(ab_pkg) < 0 )
439 return NULL;
440
441 return ab_pkg;
442 }
443
444 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
445 {
446 memset(ab_pkg, 0, sizeof(abstract_pkg_t));
447
448 ab_pkg->provided_by = abstract_pkg_vec_alloc();
449 if (ab_pkg->provided_by==NULL){
450 return -1;
451 }
452 ab_pkg->dependencies_checked = 0;
453 ab_pkg->state_status = SS_NOT_INSTALLED;
454
455 return 0;
456 }
457
458 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
459 char * temp_str;
460 char **raw =NULL;
461 char **raw_start=NULL;
462
463 temp_str = (char *) malloc (strlen(pkg->dest->info_dir)+strlen(pkg->name)+12);
464 if (temp_str == NULL ){
465 opkg_message(conf, OPKG_INFO, "Out of memory in %s\n", __FUNCTION__);
466 return;
467 }
468 sprintf( temp_str,"%s/%s.control",pkg->dest->info_dir,pkg->name);
469
470 raw = raw_start = read_raw_pkgs_from_file(temp_str);
471 if (raw == NULL ){
472 opkg_message(conf, OPKG_ERROR, "Unable to open the control file in %s\n", __FUNCTION__);
473 return;
474 }
475
476 while(*raw){
477 if (!pkg_valorize_other_field(pkg, &raw ) == 0) {
478 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
479 }
480 }
481 raw = raw_start;
482 while (*raw) {
483 if (raw!=NULL)
484 free(*raw++);
485 }
486
487 free(raw_start);
488 free(temp_str);
489
490 return ;
491
492 }
493
494 char * pkg_formatted_info(pkg_t *pkg )
495 {
496 char *line;
497 char * buff;
498
499 buff = malloc(8192);
500 if (buff == NULL) {
501 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
502 return NULL;
503 }
504
505 buff[0] = '\0';
506
507 line = pkg_formatted_field(pkg, "Package");
508 strncat(buff ,line, strlen(line));
509 free(line);
510
511 line = pkg_formatted_field(pkg, "Version");
512 strncat(buff ,line, strlen(line));
513 free(line);
514
515 line = pkg_formatted_field(pkg, "Depends");
516 strncat(buff ,line, strlen(line));
517 free(line);
518
519 line = pkg_formatted_field(pkg, "Recommends");
520 strncat(buff ,line, strlen(line));
521 free(line);
522
523 line = pkg_formatted_field(pkg, "Suggests");
524 strncat(buff ,line, strlen(line));
525 free(line);
526
527 line = pkg_formatted_field(pkg, "Provides");
528 strncat(buff ,line, strlen(line));
529 free(line);
530
531 line = pkg_formatted_field(pkg, "Replaces");
532 strncat(buff ,line, strlen(line));
533 free(line);
534
535 line = pkg_formatted_field(pkg, "Conflicts");
536 strncat(buff ,line, strlen(line));
537 free(line);
538
539 line = pkg_formatted_field(pkg, "Status");
540 strncat(buff ,line, strlen(line));
541 free(line);
542
543 line = pkg_formatted_field(pkg, "Section");
544 strncat(buff ,line, strlen(line));
545 free(line);
546
547 line = pkg_formatted_field(pkg, "Essential"); /* @@@@ should be removed in future release. *//* I do not agree with this Pigi*/
548 strncat(buff ,line, strlen(line));
549 free(line);
550
551 line = pkg_formatted_field(pkg, "Architecture");
552 strncat(buff ,line, strlen(line));
553 free(line);
554
555 line = pkg_formatted_field(pkg, "Maintainer");
556 strncat(buff ,line, strlen(line));
557 free(line);
558
559 line = pkg_formatted_field(pkg, "MD5sum");
560 strncat(buff ,line, strlen(line));
561 free(line);
562
563 line = pkg_formatted_field(pkg, "Size");
564 strncat(buff ,line, strlen(line));
565 free(line);
566
567 line = pkg_formatted_field(pkg, "Filename");
568 strncat(buff ,line, strlen(line));
569 free(line);
570
571 line = pkg_formatted_field(pkg, "Conffiles");
572 strncat(buff ,line, strlen(line));
573 free(line);
574
575 line = pkg_formatted_field(pkg, "Source");
576 strncat(buff ,line, strlen(line));
577 free(line);
578
579 line = pkg_formatted_field(pkg, "Description");
580 strncat(buff ,line, strlen(line));
581 free(line);
582
583 line = pkg_formatted_field(pkg, "Installed-Time");
584 strncat(buff ,line, strlen(line));
585 free(line);
586
587 line = pkg_formatted_field(pkg, "Tags");
588 strncat(buff ,line, strlen(line));
589 free(line);
590
591 return buff;
592 }
593
594 char * pkg_formatted_field(pkg_t *pkg, const char *field )
595 {
596 static size_t LINE_LEN = 128;
597 char * temp = (char *)malloc(1);
598 int len = 0;
599 int flag_provide_false = 0;
600
601 /*
602 Pigi: After some discussion with Florian we decided to modify the full procedure in
603 dynamic memory allocation. This should avoid any other segv in this area ( except for bugs )
604 */
605
606 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
607 goto UNKNOWN_FMT_FIELD;
608 }
609
610 temp[0]='\0';
611
612 switch (field[0])
613 {
614 case 'a':
615 case 'A':
616 if (strcasecmp(field, "Architecture") == 0) {
617 /* Architecture */
618 if (pkg->architecture) {
619 temp = (char *)realloc(temp,strlen(pkg->architecture)+17);
620 if ( temp == NULL ){
621 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
622 return NULL;
623 }
624 temp[0]='\0';
625 snprintf(temp, (strlen(pkg->architecture)+17), "Architecture: %s\n", pkg->architecture);
626 }
627 } else if (strcasecmp(field, "Auto-Installed") == 0) {
628 /* Auto-Installed flag */
629 if (pkg->auto_installed) {
630 char * s = "Auto-Installed: yes\n";
631 temp = (char *)realloc(temp, strlen(s) + 1);
632 strcpy (temp, s);
633 }
634 } else {
635 goto UNKNOWN_FMT_FIELD;
636 }
637 break;
638 case 'c':
639 case 'C':
640 if (strcasecmp(field, "Conffiles") == 0) {
641 /* Conffiles */
642 conffile_list_elt_t *iter;
643 char confstr[LINE_LEN];
644
645 if (pkg->conffiles.head == NULL) {
646 return temp;
647 }
648
649 len = 14 ;
650 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
651 if (iter->data->name && iter->data->value) {
652 len = len + (strlen(iter->data->name)+strlen(iter->data->value)+5);
653 }
654 }
655 temp = (char *)realloc(temp,len);
656 if ( temp == NULL ){
657 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
658 return NULL;
659 }
660 temp[0]='\0';
661 strncpy(temp, "Conffiles:\n", 12);
662 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
663 if (iter->data->name && iter->data->value) {
664 snprintf(confstr, LINE_LEN, "%s %s\n", iter->data->name, iter->data->value);
665 strncat(temp, confstr, strlen(confstr));
666 }
667 }
668 } else if (strcasecmp(field, "Conflicts") == 0) {
669 int i;
670
671 if (pkg->conflicts_count) {
672 char conflictstr[LINE_LEN];
673 len = 14 ;
674 for(i = 0; i < pkg->conflicts_count; i++) {
675 len = len + (strlen(pkg->conflicts_str[i])+5);
676 }
677 temp = (char *)realloc(temp,len);
678 if ( temp == NULL ){
679 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
680 return NULL;
681 }
682 temp[0]='\0';
683 strncpy(temp, "Conflicts:", 11);
684 for(i = 0; i < pkg->conflicts_count; i++) {
685 snprintf(conflictstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
686 strncat(temp, conflictstr, strlen(conflictstr));
687 }
688 strncat(temp, "\n", strlen("\n"));
689 }
690 } else {
691 goto UNKNOWN_FMT_FIELD;
692 }
693 break;
694 case 'd':
695 case 'D':
696 if (strcasecmp(field, "Depends") == 0) {
697 /* Depends */
698 int i;
699
700 if (pkg->depends_count) {
701 char depstr[LINE_LEN];
702 len = 14 ;
703 for(i = 0; i < pkg->depends_count; i++) {
704 len = len + (strlen(pkg->depends_str[i])+4);
705 }
706 temp = (char *)realloc(temp,len);
707 if ( temp == NULL ){
708 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
709 return NULL;
710 }
711 temp[0]='\0';
712 strncpy(temp, "Depends:", 10);
713 for(i = 0; i < pkg->depends_count; i++) {
714 snprintf(depstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
715 strncat(temp, depstr, strlen(depstr));
716 }
717 strncat(temp, "\n", strlen("\n"));
718 }
719 } else if (strcasecmp(field, "Description") == 0) {
720 /* Description */
721 if (pkg->description) {
722 temp = (char *)realloc(temp,strlen(pkg->description)+16);
723 if ( temp == NULL ){
724 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
725 return NULL;
726 }
727 temp[0]='\0';
728 snprintf(temp, (strlen(pkg->description)+16), "Description: %s\n", pkg->description);
729 }
730 } else {
731 goto UNKNOWN_FMT_FIELD;
732 }
733 break;
734 case 'e':
735 case 'E': {
736 /* Essential */
737 if (pkg->essential) {
738 temp = (char *)realloc(temp,16);
739 if ( temp == NULL ){
740 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
741 return NULL;
742 }
743 temp[0]='\0';
744 snprintf(temp, (16), "Essential: yes\n");
745 }
746 }
747 break;
748 case 'f':
749 case 'F': {
750 /* Filename */
751 if (pkg->filename) {
752 temp = (char *)realloc(temp,strlen(pkg->filename)+12);
753 if ( temp == NULL ){
754 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
755 return NULL;
756 }
757 temp[0]='\0';
758 snprintf(temp, (strlen(pkg->filename)+12), "Filename: %s\n", pkg->filename);
759 }
760 }
761 break;
762 case 'i':
763 case 'I': {
764 if (strcasecmp(field, "Installed-Size") == 0) {
765 /* Installed-Size */
766 temp = (char *)realloc(temp,strlen(pkg->installed_size)+17);
767 if ( temp == NULL ){
768 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
769 return NULL;
770 }
771 temp[0]='\0';
772 snprintf(temp, (strlen(pkg->installed_size)+17), "Installed-Size: %s\n", pkg->installed_size);
773 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
774 temp = (char *)realloc(temp,29);
775 if ( temp == NULL ){
776 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
777 return NULL;
778 }
779 temp[0]='\0';
780 snprintf(temp, 29, "Installed-Time: %lu\n", pkg->installed_time);
781 }
782 }
783 break;
784 case 'm':
785 case 'M': {
786 /* Maintainer | MD5sum */
787 if (strcasecmp(field, "Maintainer") == 0) {
788 /* Maintainer */
789 if (pkg->maintainer) {
790 temp = (char *)realloc(temp,strlen(pkg->maintainer)+14);
791 if ( temp == NULL ){
792 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
793 return NULL;
794 }
795 temp[0]='\0';
796 snprintf(temp, (strlen(pkg->maintainer)+14), "maintainer: %s\n", pkg->maintainer);
797 }
798 } else if (strcasecmp(field, "MD5sum") == 0) {
799 /* MD5sum */
800 if (pkg->md5sum) {
801 temp = (char *)realloc(temp,strlen(pkg->md5sum)+11);
802 if ( temp == NULL ){
803 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
804 return NULL;
805 }
806 temp[0]='\0';
807 snprintf(temp, (strlen(pkg->md5sum)+11), "MD5Sum: %s\n", pkg->md5sum);
808 }
809 } else {
810 goto UNKNOWN_FMT_FIELD;
811 }
812 }
813 break;
814 case 'p':
815 case 'P': {
816 if (strcasecmp(field, "Package") == 0) {
817 /* Package */
818 temp = (char *)realloc(temp,strlen(pkg->name)+11);
819 if ( temp == NULL ){
820 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
821 return NULL;
822 }
823 temp[0]='\0';
824 snprintf(temp, (strlen(pkg->name)+11), "Package: %s\n", pkg->name);
825 } else if (strcasecmp(field, "Priority") == 0) {
826 /* Priority */
827 temp = (char *)realloc(temp,strlen(pkg->priority)+12);
828 if ( temp == NULL ){
829 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
830 return NULL;
831 }
832 temp[0]='\0';
833 snprintf(temp, (strlen(pkg->priority)+12), "Priority: %s\n", pkg->priority);
834 } else if (strcasecmp(field, "Provides") == 0) {
835 /* Provides */
836 int i;
837
838 if (pkg->provides_count) {
839 /* Here we check if the opkg_internal_use_only is used, and we discard it.*/
840 for ( i=0; i < pkg->provides_count; i++ ){
841 if (strstr(pkg->provides_str[i],"opkg_internal_use_only")!=NULL) {
842 memset (pkg->provides_str[i],'\x0',strlen(pkg->provides_str[i])); /* Pigi clear my trick flag, just in case */
843 flag_provide_false = 1;
844 }
845 }
846 if ( !flag_provide_false || /* Pigi there is not my trick flag */
847 ((flag_provide_false) && (pkg->provides_count > 1))){ /* Pigi There is, but we also have others Provides */
848 char provstr[LINE_LEN];
849 len = 15;
850 for(i = 0; i < pkg->provides_count; i++) {
851 len = len + (strlen(pkg->provides_str[i])+5);
852 }
853 temp = (char *)realloc(temp,len);
854 if ( temp == NULL ){
855 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
856 return NULL;
857 }
858 temp[0]='\0';
859 strncpy(temp, "Provides:", 12);
860 for(i = 0; i < pkg->provides_count; i++) {
861 if (strlen(pkg->provides_str[i])>0){;
862 snprintf(provstr, LINE_LEN, "%s %s", i == 1 ? "" : ",", pkg->provides_str[i]);
863 strncat(temp, provstr, strlen(provstr));
864 }
865 }
866 strncat(temp, "\n", strlen("\n"));
867 }
868 }
869 } else {
870 goto UNKNOWN_FMT_FIELD;
871 }
872 }
873 break;
874 case 'r':
875 case 'R': {
876 int i;
877 /* Replaces | Recommends*/
878 if (strcasecmp (field, "Replaces") == 0) {
879 if (pkg->replaces_count) {
880 char replstr[LINE_LEN];
881 len = 14;
882 for (i = 0; i < pkg->replaces_count; i++) {
883 len = len + (strlen(pkg->replaces_str[i])+5);
884 }
885 temp = (char *)realloc(temp,len);
886 if ( temp == NULL ){
887 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
888 return NULL;
889 }
890 temp[0]='\0';
891 strncpy(temp, "Replaces:", 12);
892 for (i = 0; i < pkg->replaces_count; i++) {
893 snprintf(replstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
894 strncat(temp, replstr, strlen(replstr));
895 }
896 strncat(temp, "\n", strlen("\n"));
897 }
898 } else if (strcasecmp (field, "Recommends") == 0) {
899 if (pkg->recommends_count) {
900 char recstr[LINE_LEN];
901 len = 15;
902 for(i = 0; i < pkg->recommends_count; i++) {
903 len = len + (strlen( pkg->recommends_str[i])+5);
904 }
905 temp = (char *)realloc(temp,len);
906 if ( temp == NULL ){
907 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
908 return NULL;
909 }
910 temp[0]='\0';
911 strncpy(temp, "Recommends:", 13);
912 for(i = 0; i < pkg->recommends_count; i++) {
913 snprintf(recstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
914 strncat(temp, recstr, strlen(recstr));
915 }
916 strncat(temp, "\n", strlen("\n"));
917 }
918 } else {
919 goto UNKNOWN_FMT_FIELD;
920 }
921 }
922 break;
923 case 's':
924 case 'S': {
925 /* Section | Size | Source | Status | Suggests */
926 if (strcasecmp(field, "Section") == 0) {
927 /* Section */
928 if (pkg->section) {
929 temp = (char *)realloc(temp,strlen(pkg->section)+11);
930 if ( temp == NULL ){
931 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
932 return NULL;
933 }
934 temp[0]='\0';
935 snprintf(temp, (strlen(pkg->section)+11), "Section: %s\n", pkg->section);
936 }
937 } else if (strcasecmp(field, "Size") == 0) {
938 /* Size */
939 if (pkg->size) {
940 temp = (char *)realloc(temp,strlen(pkg->size)+8);
941 if ( temp == NULL ){
942 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
943 return NULL;
944 }
945 temp[0]='\0';
946 snprintf(temp, (strlen(pkg->size)+8), "Size: %s\n", pkg->size);
947 }
948 } else if (strcasecmp(field, "Source") == 0) {
949 /* Source */
950 if (pkg->source) {
951 temp = (char *)realloc(temp,strlen(pkg->source)+10);
952 if ( temp == NULL ){
953 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
954 return NULL;
955 }
956 temp[0]='\0';
957 snprintf(temp, (strlen(pkg->source)+10), "Source: %s\n", pkg->source);
958 }
959 } else if (strcasecmp(field, "Status") == 0) {
960 /* Status */
961 /* Benjamin Pineau note: we should avoid direct usage of
962 * strlen(arg) without keeping "arg" for later free()
963 */
964 char *pflag=pkg_state_flag_to_str(pkg->state_flag);
965 char *pstat=pkg_state_status_to_str(pkg->state_status);
966 char *pwant=pkg_state_want_to_str(pkg->state_want);
967
968 size_t sum_of_sizes = (size_t) ( strlen(pwant)+ strlen(pflag)+ strlen(pstat) + 12 );
969 temp = (char *)realloc(temp,sum_of_sizes);
970 if ( temp == NULL ){
971 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
972 return NULL;
973 }
974 temp[0]='\0';
975 snprintf(temp, sum_of_sizes , "Status: %s %s %s\n", pwant, pflag, pstat);
976 free(pflag);
977 free(pwant);
978 if(pstat) /* pfstat can be NULL if ENOMEM */
979 free(pstat);
980 } else if (strcasecmp(field, "Suggests") == 0) {
981 if (pkg->suggests_count) {
982 int i;
983 char sugstr[LINE_LEN];
984 len = 13;
985 for(i = 0; i < pkg->suggests_count; i++) {
986 len = len + (strlen(pkg->suggests_str[i])+5);
987 }
988 temp = (char *)realloc(temp,len);
989 if ( temp == NULL ){
990 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
991 return NULL;
992 }
993 temp[0]='\0';
994 strncpy(temp, "Suggests:", 10);
995 for(i = 0; i < pkg->suggests_count; i++) {
996 snprintf(sugstr, LINE_LEN, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
997 strncat(temp, sugstr, strlen(sugstr));
998 }
999 strncat(temp, "\n", strlen("\n"));
1000 }
1001 } else {
1002 goto UNKNOWN_FMT_FIELD;
1003 }
1004 }
1005 break;
1006 case 't':
1007 case 'T':
1008 if (strcasecmp(field, "Tags") == 0) {
1009 /* Tags */
1010 if (pkg->tags) {
1011 temp = (char *)realloc(temp,strlen(pkg->tags)+8);
1012 if ( temp == NULL ){
1013 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1014 return NULL;
1015 }
1016 temp[0]='\0';
1017 snprintf(temp, (strlen(pkg->tags)+8), "Tags: %s\n", pkg->tags);
1018 }
1019 }
1020 break;
1021 case 'v':
1022 case 'V': {
1023 /* Version */
1024 char *version = pkg_version_str_alloc(pkg);
1025 temp = (char *)realloc(temp,strlen(version)+14);
1026 if ( temp == NULL ){
1027 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1028 return NULL;
1029 }
1030 temp[0]='\0';
1031 snprintf(temp, (strlen(version)+12), "Version: %s\n", version);
1032 free(version);
1033 }
1034 break;
1035 default:
1036 goto UNKNOWN_FMT_FIELD;
1037 }
1038
1039 if ( strlen(temp)<2 ) {
1040 temp[0]='\0';
1041 }
1042 return temp;
1043
1044 UNKNOWN_FMT_FIELD:
1045 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
1046 if ( strlen(temp)<2 ) {
1047 temp[0]='\0';
1048 }
1049
1050 return temp;
1051 }
1052
1053 void pkg_print_info(pkg_t *pkg, FILE *file)
1054 {
1055 int t=0;
1056 char * buff;
1057 if (pkg == NULL) {
1058 return;
1059 }
1060
1061 buff = pkg_formatted_info(pkg);
1062 if ( buff == NULL )
1063 return;
1064 if (strlen(buff)>2){
1065 t = fwrite(buff, 1, strlen(buff), file); //#~rzr:TODO
1066 }
1067 free(buff);
1068 }
1069
1070 void pkg_print_status(pkg_t * pkg, FILE * file)
1071 {
1072 if (pkg == NULL) {
1073 return;
1074 }
1075
1076 /* XXX: QUESTION: Do we actually want more fields here? The
1077 original idea was to save space by installing only what was
1078 needed for actual computation, (package, version, status,
1079 essential, conffiles). The assumption is that all other fields
1080 can be found in th available file.
1081
1082 But, someone proposed the idea to make it possible to
1083 reconstruct a .opk from an installed package, (ie. for beaming
1084 from one handheld to another). So, maybe we actually want a few
1085 more fields here, (depends, suggests, etc.), so that that would
1086 be guaranteed to work even in the absence of more information
1087 from the available file.
1088
1089 28-MAR-03: kergoth and I discussed this yesterday. We think
1090 the essential info needs to be here for all installed packages
1091 because they may not appear in the Packages files on various
1092 feeds. Furthermore, one should be able to install from URL or
1093 local storage without requiring a Packages file from any feed.
1094 -Jamey
1095 */
1096 pkg_print_field(pkg, file, "Package");
1097 pkg_print_field(pkg, file, "Version");
1098 pkg_print_field(pkg, file, "Depends");
1099 pkg_print_field(pkg, file, "Recommends");
1100 pkg_print_field(pkg, file, "Suggests");
1101 pkg_print_field(pkg, file, "Provides");
1102 pkg_print_field(pkg, file, "Replaces");
1103 pkg_print_field(pkg, file, "Conflicts");
1104 pkg_print_field(pkg, file, "Status");
1105 pkg_print_field(pkg, file, "Essential"); /* @@@@ should be removed in future release. */
1106 pkg_print_field(pkg, file, "Architecture");
1107 pkg_print_field(pkg, file, "Conffiles");
1108 pkg_print_field(pkg, file, "Installed-Time");
1109 pkg_print_field(pkg, file, "Auto-Installed");
1110 fputs("\n", file);
1111 }
1112
1113 void pkg_print_field(pkg_t *pkg, FILE *file, const char *field)
1114 {
1115 char *buff;
1116 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
1117 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n",
1118 __FUNCTION__, field);
1119 }
1120 buff = pkg_formatted_field(pkg, field);
1121 if (strlen(buff)>2) {
1122 fprintf(file, "%s", buff);
1123 fflush(file);
1124 }
1125 free(buff);
1126 return;
1127 }
1128
1129 /*
1130 * libdpkg - Debian packaging suite library routines
1131 * vercmp.c - comparison of version numbers
1132 *
1133 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
1134 */
1135 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
1136 {
1137 int r;
1138
1139 if (pkg->epoch > ref_pkg->epoch) {
1140 return 1;
1141 }
1142
1143 if (pkg->epoch < ref_pkg->epoch) {
1144 return -1;
1145 }
1146
1147 r = verrevcmp(pkg->version, ref_pkg->version);
1148 if (r) {
1149 return r;
1150 }
1151
1152 r = verrevcmp(pkg->revision, ref_pkg->revision);
1153 if (r) {
1154 return r;
1155 }
1156
1157 return r;
1158 }
1159
1160 /* assume ascii; warning: evaluates x multiple times! */
1161 #define order(x) ((x) == '~' ? -1 \
1162 : isdigit((x)) ? 0 \
1163 : !(x) ? 0 \
1164 : isalpha((x)) ? (x) \
1165 : (x) + 256)
1166
1167 static int verrevcmp(const char *val, const char *ref) {
1168 if (!val) val= "";
1169 if (!ref) ref= "";
1170
1171 while (*val || *ref) {
1172 int first_diff= 0;
1173
1174 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
1175 int vc= order(*val), rc= order(*ref);
1176 if (vc != rc) return vc - rc;
1177 val++; ref++;
1178 }
1179
1180 while ( *val == '0' ) val++;
1181 while ( *ref == '0' ) ref++;
1182 while (isdigit(*val) && isdigit(*ref)) {
1183 if (!first_diff) first_diff= *val - *ref;
1184 val++; ref++;
1185 }
1186 if (isdigit(*val)) return 1;
1187 if (isdigit(*ref)) return -1;
1188 if (first_diff) return first_diff;
1189 }
1190 return 0;
1191 }
1192
1193 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
1194 {
1195 int r;
1196
1197 r = pkg_compare_versions(it, ref);
1198
1199 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
1200 return r <= 0;
1201 }
1202
1203 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
1204 return r >= 0;
1205 }
1206
1207 if (strcmp(op, "<<") == 0) {
1208 return r < 0;
1209 }
1210
1211 if (strcmp(op, ">>") == 0) {
1212 return r > 0;
1213 }
1214
1215 if (strcmp(op, "=") == 0) {
1216 return r == 0;
1217 }
1218
1219 fprintf(stderr, "unknown operator: %s", op);
1220 return 0;
1221 }
1222
1223 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
1224 {
1225 const pkg_t *a = *(const pkg_t**) p1;
1226 const pkg_t *b = *(const pkg_t**) p2;
1227 int namecmp;
1228 int vercmp;
1229 if (!a->name || !b->name) {
1230 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
1231 a, a->name, b, b->name);
1232 return 0;
1233 }
1234
1235 namecmp = strcmp(a->name, b->name);
1236 if (namecmp)
1237 return namecmp;
1238 vercmp = pkg_compare_versions(a, b);
1239 if (vercmp)
1240 return vercmp;
1241 if (!a->arch_priority || !b->arch_priority) {
1242 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
1243 a, a->arch_priority, b, b->arch_priority);
1244 return 0;
1245 }
1246 if (a->arch_priority > b->arch_priority)
1247 return 1;
1248 if (a->arch_priority < b->arch_priority)
1249 return -1;
1250 return 0;
1251 }
1252
1253 int abstract_pkg_name_compare(const void *p1, const void *p2)
1254 {
1255 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1256 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1257 if (!a->name || !b->name) {
1258 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
1259 a, a->name, b, b->name);
1260 return 0;
1261 }
1262 return strcmp(a->name, b->name);
1263 }
1264
1265
1266 char *pkg_version_str_alloc(pkg_t *pkg)
1267 {
1268 char *complete_version;
1269 char *epoch_str;
1270 char *revision_str;
1271
1272 if (pkg->epoch) {
1273 sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
1274 } else {
1275 epoch_str = strdup("");
1276 }
1277
1278 if (pkg->revision && strlen(pkg->revision)) {
1279 sprintf_alloc(&revision_str, "-%s", pkg->revision);
1280 } else {
1281 revision_str = strdup("");
1282 }
1283
1284
1285 sprintf_alloc(&complete_version, "%s%s%s",
1286 epoch_str, pkg->version, revision_str);
1287
1288 free(epoch_str);
1289 free(revision_str);
1290
1291 return complete_version;
1292 }
1293
1294 str_list_t *pkg_get_installed_files(pkg_t *pkg)
1295 {
1296 int err;
1297 char *list_file_name = NULL;
1298 FILE *list_file = NULL;
1299 char *line;
1300 char *installed_file_name;
1301 int rootdirlen;
1302
1303 pkg->installed_files_ref_cnt++;
1304
1305 if (pkg->installed_files) {
1306 return pkg->installed_files;
1307 }
1308
1309 pkg->installed_files = str_list_alloc();
1310 if (pkg->installed_files == NULL) {
1311 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1312 return NULL;
1313 }
1314
1315 /* For uninstalled packages, get the file list firectly from the package.
1316 For installed packages, look at the package.list file in the database.
1317 */
1318 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1319 if (pkg->local_filename == NULL) {
1320 return pkg->installed_files;
1321 }
1322 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1323 file. In other words, change deb_extract so that it can
1324 simply return the file list as a char *[] rather than
1325 insisting on writing in to a FILE * as it does now. */
1326 list_file = tmpfile();
1327 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1328 if (err) {
1329 fclose(list_file);
1330 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1331 __FUNCTION__, pkg->local_filename, strerror(err));
1332 return pkg->installed_files;
1333 }
1334 rewind(list_file);
1335 } else {
1336 sprintf_alloc(&list_file_name, "%s/%s.list",
1337 pkg->dest->info_dir, pkg->name);
1338 if (! file_exists(list_file_name)) {
1339 free(list_file_name);
1340 return pkg->installed_files;
1341 }
1342
1343 list_file = fopen(list_file_name, "r");
1344 if (list_file == NULL) {
1345 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1346 list_file_name, strerror(errno));
1347 free(list_file_name);
1348 return pkg->installed_files;
1349 }
1350 free(list_file_name);
1351 }
1352
1353 rootdirlen = strlen( pkg->dest->root_dir );
1354 while (1) {
1355 char *file_name;
1356
1357 line = file_read_line_alloc(list_file);
1358 if (line == NULL) {
1359 break;
1360 }
1361 str_chomp(line);
1362 file_name = line;
1363
1364 /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1365 if( strncmp( pkg->dest->root_dir,
1366 file_name,
1367 rootdirlen ) ) {
1368 if (*file_name == '.') {
1369 file_name++;
1370 }
1371 if (*file_name == '/') {
1372 file_name++;
1373 }
1374
1375 /* Freed in pkg_free_installed_files */
1376 sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1377 } else {
1378 // already contains root_dir as header -> ABSOLUTE
1379 sprintf_alloc(&installed_file_name, "%s", file_name);
1380 }
1381 str_list_append(pkg->installed_files, installed_file_name);
1382 free(line);
1383 }
1384
1385 fclose(list_file);
1386
1387 return pkg->installed_files;
1388 }
1389
1390 /* XXX: CLEANUP: This function and it's counterpart,
1391 (pkg_get_installed_files), do not match our init/deinit naming
1392 convention. Nor the alloc/free convention. But, then again, neither
1393 of these conventions currrently fit the way these two functions
1394 work. */
1395 int pkg_free_installed_files(pkg_t *pkg)
1396 {
1397 str_list_elt_t *iter;
1398
1399 pkg->installed_files_ref_cnt--;
1400 if (pkg->installed_files_ref_cnt > 0) {
1401 return 0;
1402 }
1403
1404 if (pkg->installed_files) {
1405
1406 for (iter = pkg->installed_files->head; iter; iter = iter->next) {
1407 /* malloced in pkg_get_installed_files */
1408 free (iter->data);
1409 iter->data = NULL;
1410 }
1411
1412 str_list_deinit(pkg->installed_files);
1413 free (pkg->installed_files);
1414 }
1415
1416 pkg->installed_files = NULL;
1417
1418 return 0;
1419 }
1420
1421 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1422 {
1423 int err;
1424 char *list_file_name;
1425
1426 //I don't think pkg_free_installed_files should be called here. Jamey
1427 //pkg_free_installed_files(pkg);
1428
1429 sprintf_alloc(&list_file_name, "%s/%s.list",
1430 pkg->dest->info_dir, pkg->name);
1431 if (!conf->noaction) {
1432 err = unlink(list_file_name);
1433 free(list_file_name);
1434
1435 if (err) {
1436 return errno;
1437 }
1438 }
1439 return 0;
1440 }
1441
1442 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1443 {
1444 conffile_list_elt_t *iter;
1445 conffile_t *conffile;
1446
1447 if (pkg == NULL) {
1448 return NULL;
1449 }
1450
1451 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
1452 conffile = iter->data;
1453
1454 if (strcmp(conffile->name, file_name) == 0) {
1455 return conffile;
1456 }
1457 }
1458
1459 return NULL;
1460 }
1461
1462 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1463 const char *script, const char *args)
1464 {
1465 int err;
1466 char *path;
1467 char *cmd;
1468
1469 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1470 maintainer script within a chroot environment. */
1471
1472 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1473 have scripts in pkg->tmp_unpack_dir. */
1474 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1475 if (pkg->dest == NULL) {
1476 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1477 __FUNCTION__, pkg->name);
1478 return EINVAL;
1479 }
1480 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1481 } else {
1482 if (pkg->tmp_unpack_dir == NULL) {
1483 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1484 __FUNCTION__, pkg->name);
1485 return EINVAL;
1486 }
1487 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1488 }
1489
1490 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1491 if (conf->noaction) return 0;
1492
1493 /* XXX: CLEANUP: There must be a better way to handle maintainer
1494 scripts when running with offline_root mode and/or a dest other
1495 than '/'. I've been playing around with some clever chroot
1496 tricks and I might come up with something workable. */
1497 if (conf->offline_root) {
1498 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1499 }
1500
1501 setenv("PKG_ROOT",
1502 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1503
1504 if (! file_exists(path)) {
1505 free(path);
1506 return 0;
1507 }
1508
1509 if (conf->offline_root) {
1510 fprintf(stderr, "(offline root mode: not running %s.%s)\n", pkg->name, script);
1511 free(path);
1512 return 0;
1513 }
1514
1515 sprintf_alloc(&cmd, "%s %s", path, args);
1516 free(path);
1517
1518 err = xsystem(cmd);
1519 free(cmd);
1520
1521 if (err) {
1522 fprintf(stderr, "%s script returned status %d\n", script, err);
1523 return err;
1524 }
1525
1526 return 0;
1527 }
1528
1529 char *pkg_state_want_to_str(pkg_state_want_t sw)
1530 {
1531 int i;
1532
1533 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1534 if (pkg_state_want_map[i].value == sw) {
1535 return strdup(pkg_state_want_map[i].str);
1536 }
1537 }
1538
1539 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1540 __FUNCTION__, sw);
1541 return strdup("<STATE_WANT_UNKNOWN>");
1542 }
1543
1544 pkg_state_want_t pkg_state_want_from_str(char *str)
1545 {
1546 int i;
1547
1548 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1549 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1550 return pkg_state_want_map[i].value;
1551 }
1552 }
1553
1554 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1555 __FUNCTION__, str);
1556 return SW_UNKNOWN;
1557 }
1558
1559 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1560 {
1561 int i;
1562 int len = 3; /* ok\000 is minimum */
1563 char *str = NULL;
1564
1565 /* clear the temporary flags before converting to string */
1566 sf &= SF_NONVOLATILE_FLAGS;
1567
1568 if (sf == 0) {
1569 return strdup("ok");
1570 } else {
1571
1572 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1573 if (sf & pkg_state_flag_map[i].value) {
1574 len += strlen(pkg_state_flag_map[i].str) + 1;
1575 }
1576 }
1577 str = malloc(len);
1578 if ( str == NULL ) {
1579 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1580 return NULL;
1581 }
1582 str[0] = 0;
1583 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1584 if (sf & pkg_state_flag_map[i].value) {
1585 strcat(str, pkg_state_flag_map[i].str);
1586 strcat(str, ",");
1587 }
1588 }
1589 len = strlen(str);
1590 str[len-1] = 0; /* squash last comma */
1591 return str;
1592 }
1593 }
1594
1595 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1596 {
1597 int i;
1598 int sf = SF_OK;
1599
1600 if (strcmp(str, "ok") == 0) {
1601 return SF_OK;
1602 }
1603 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1604 const char *sfname = pkg_state_flag_map[i].str;
1605 int sfname_len = strlen(sfname);
1606 if (strncmp(str, sfname, sfname_len) == 0) {
1607 sf |= pkg_state_flag_map[i].value;
1608 str += sfname_len;
1609 if (str[0] == ',') {
1610 str++;
1611 } else {
1612 break;
1613 }
1614 }
1615 }
1616
1617 return sf;
1618 }
1619
1620 char *pkg_state_status_to_str(pkg_state_status_t ss)
1621 {
1622 int i;
1623
1624 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1625 if (pkg_state_status_map[i].value == ss) {
1626 return strdup(pkg_state_status_map[i].str);
1627 }
1628 }
1629
1630 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1631 __FUNCTION__, ss);
1632 return strdup("<STATE_STATUS_UNKNOWN>");
1633 }
1634
1635 pkg_state_status_t pkg_state_status_from_str(const char *str)
1636 {
1637 int i;
1638
1639 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1640 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1641 return pkg_state_status_map[i].value;
1642 }
1643 }
1644
1645 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1646 __FUNCTION__, str);
1647 return SS_NOT_INSTALLED;
1648 }
1649
1650 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1651 {
1652 nv_pair_list_elt_t *l;
1653
1654 if (!pkg->architecture)
1655 return 1;
1656
1657 l = conf->arch_list.head;
1658
1659 while (l) {
1660 nv_pair_t *nv = l->data;
1661 if (strcmp(nv->name, pkg->architecture) == 0) {
1662 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1663 return 1;
1664 }
1665 l = l->next;
1666 }
1667
1668 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1669 return 0;
1670 }
1671
1672 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1673 {
1674 nv_pair_list_elt_t *l;
1675
1676 l = conf->arch_list.head;
1677
1678 while (l) {
1679 nv_pair_t *nv = l->data;
1680 if (strcmp(nv->name, archname) == 0) {
1681 int priority = strtol(nv->value, NULL, 0);
1682 return priority;
1683 }
1684 l = l->next;
1685 }
1686 return 0;
1687 }
1688
1689 int pkg_info_preinstall_check(opkg_conf_t *conf)
1690 {
1691 int i;
1692 hash_table_t *pkg_hash = &conf->pkg_hash;
1693 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1694 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1695
1696 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1697 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1698 /* update arch_priority for each package */
1699 for (i = 0; i < available_pkgs->len; i++) {
1700 pkg_t *pkg = available_pkgs->pkgs[i];
1701 int arch_priority = 1;
1702 if (!pkg)
1703 continue;
1704 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1705 if (pkg->architecture)
1706 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1707 else
1708 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1709 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1710 pkg->arch_priority = arch_priority;
1711 }
1712
1713 for (i = 0; i < available_pkgs->len; i++) {
1714 pkg_t *pkg = available_pkgs->pkgs[i];
1715 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1716 /* clear flags and want for any uninstallable package */
1717 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1718 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1719 pkg->state_want = SW_UNKNOWN;
1720 pkg->state_flag = 0;
1721 }
1722 }
1723 pkg_vec_free(available_pkgs);
1724
1725 /* update the file owner data structure */
1726 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1727 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1728 for (i = 0; i < installed_pkgs->len; i++) {
1729 pkg_t *pkg = installed_pkgs->pkgs[i];
1730 str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1731 str_list_elt_t *iter;
1732 if (installed_files == NULL) {
1733 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1734 break;
1735 }
1736 for (iter = installed_files->head; iter; iter = iter->next) {
1737 char *installed_file = iter->data;
1738 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1739 file_hash_set_file_owner(conf, installed_file, pkg);
1740 }
1741 pkg_free_installed_files(pkg);
1742 }
1743 pkg_vec_free(installed_pkgs);
1744
1745 return 0;
1746 }
1747
1748 struct pkg_write_filelist_data {
1749 opkg_conf_t *conf;
1750 pkg_t *pkg;
1751 FILE *stream;
1752 };
1753
1754 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1755 {
1756 struct pkg_write_filelist_data *data = data_;
1757 pkg_t *entry = entry_;
1758 if (entry == data->pkg) {
1759 fprintf(data->stream, "%s\n", key);
1760 }
1761 }
1762
1763 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1764 {
1765 struct pkg_write_filelist_data data;
1766 char *list_file_name = NULL;
1767 int err = 0;
1768
1769 if (!pkg) {
1770 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1771 return -EINVAL;
1772 }
1773 opkg_message(conf, OPKG_INFO,
1774 " creating %s.list file\n", pkg->name);
1775 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1776 if (!list_file_name) {
1777 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1778 return -ENOMEM;
1779 }
1780 opkg_message(conf, OPKG_INFO,
1781 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1782 data.stream = fopen(list_file_name, "w");
1783 if (!data.stream) {
1784 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1785 list_file_name, strerror(errno));
1786 return errno;
1787 }
1788 data.pkg = pkg;
1789 data.conf = conf;
1790 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1791 fclose(data.stream);
1792 free(list_file_name);
1793
1794 return err;
1795 }
1796
1797 int pkg_write_changed_filelists(opkg_conf_t *conf)
1798 {
1799 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1800 hash_table_t *pkg_hash = &conf->pkg_hash;
1801 int i;
1802 int err;
1803 if (conf->noaction)
1804 return 0;
1805
1806 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1807 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1808 for (i = 0; i < installed_pkgs->len; i++) {
1809 pkg_t *pkg = installed_pkgs->pkgs[i];
1810 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1811 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1812 err = pkg_write_filelist(conf, pkg);
1813 if (err)
1814 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1815 }
1816 }
1817 pkg_vec_free (installed_pkgs);
1818 return 0;
1819 }