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