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