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