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