1 /* pkg.c - the opkg package management system
5 Copyright (C) 2001 University of Southern California
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.
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.
27 #include "pkg_parse.h"
28 #include "pkg_extract.h"
29 #include "opkg_message.h"
30 #include "opkg_utils.h"
32 #include "libbb/libbb.h"
33 #include "sprintf_alloc.h"
34 #include "file_util.h"
37 #include "opkg_conf.h"
39 typedef struct enum_map enum_map_t;
46 static const enum_map_t pkg_state_want_map[] = {
47 { SW_UNKNOWN, "unknown"},
48 { SW_INSTALL, "install"},
49 { SW_DEINSTALL, "deinstall"},
53 static const enum_map_t pkg_state_flag_map[] = {
55 { SF_REINSTREQ, "reinstreq"},
57 { SF_REPLACE, "replace"},
58 { SF_NOPRUNE, "noprune"},
59 { SF_PREFER, "prefer"},
60 { SF_OBSOLETE, "obsolete"},
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" }
75 static int verrevcmp(const char *val, const char *ref);
82 pkg = xcalloc(1, sizeof(pkg_t));
88 int pkg_init(pkg_t *pkg)
96 pkg->architecture = NULL;
97 pkg->maintainer = 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;
107 pkg->suggests_str = NULL;
108 pkg->recommends_str = NULL;
109 pkg->suggests_count = 0;
110 pkg->recommends_count = 0;
112 active_list_init(&pkg->list);
114 /* Abhaya: added init for conflicts fields */
115 pkg->conflicts = NULL;
116 pkg->conflicts_count = 0;
118 /* added for replaces. Jamey 7/23/2002 */
119 pkg->replaces = NULL;
120 pkg->replaces_count = 0;
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;
130 #if defined HAVE_SHA256
131 pkg->sha256sum = NULL;
134 pkg->installed_size = NULL;
135 pkg->priority = NULL;
137 conffile_list_init(&pkg->conffiles);
138 pkg->installed_files = NULL;
139 pkg->installed_files_ref_cnt = 0;
141 pkg->provided_by_hand = 0;
146 void compound_depend_deinit (compound_depend_t *depends)
149 for (i = 0; i < depends->possibility_count; i++)
152 d = depends->possibilities[i];
156 free (depends->possibilities);
159 void pkg_deinit(pkg_t *pkg)
172 /* revision shares storage with version, so don't free */
173 pkg->revision = NULL;
175 /* owned by opkg_conf_t */
177 /* owned by opkg_conf_t */
180 if (pkg->architecture)
181 free(pkg->architecture);
182 pkg->architecture = NULL;
185 free(pkg->maintainer);
186 pkg->maintainer = NULL;
192 if (pkg->description)
193 free(pkg->description);
194 pkg->description = NULL;
196 pkg->state_want = SW_UNKNOWN;
197 pkg->state_flag = SF_OK;
198 pkg->state_status = SS_NOT_INSTALLED;
200 active_list_clear(&pkg->list);
203 free (pkg->replaces);
204 pkg->replaces = NULL;
207 int count = pkg->pre_depends_count
209 + pkg->recommends_count
210 + pkg->suggests_count;
212 for (i=0; i<count; i++)
213 compound_depend_deinit (&pkg->depends[i]);
217 if (pkg->conflicts) {
218 for (i=0; i<pkg->conflicts_count; i++)
219 compound_depend_deinit (&pkg->conflicts[i]);
220 free (pkg->conflicts);
224 free (pkg->provides);
226 pkg->pre_depends_count = 0;
227 pkg->provides_count = 0;
231 pkg->filename = NULL;
233 if (pkg->local_filename)
234 free(pkg->local_filename);
235 pkg->local_filename = NULL;
237 /* CLEANUP: It'd be nice to pullin the cleanup function from
238 opkg_install.c here. See comment in
239 opkg_install.c:cleanup_temporary_files */
240 if (pkg->tmp_unpack_dir)
241 free(pkg->tmp_unpack_dir);
242 pkg->tmp_unpack_dir = NULL;
248 #if defined HAVE_SHA256
250 free(pkg->sha256sum);
251 pkg->sha256sum = NULL;
258 if (pkg->installed_size)
259 free(pkg->installed_size);
260 pkg->installed_size = NULL;
264 pkg->priority = NULL;
270 conffile_list_deinit(&pkg->conffiles);
272 /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
273 since if they are calling deinit, they should know. Maybe do an
274 assertion here instead? */
275 pkg->installed_files_ref_cnt = 1;
276 pkg_free_installed_files(pkg);
285 pkg_init_from_file(opkg_conf_t *conf, pkg_t *pkg, const char *filename)
293 pkg->local_filename = xstrdup(filename);
295 sprintf_alloc(&control_path, "%s/%s.control.XXXXXX",
298 fd = mkstemp(control_path);
300 perror_msg("%s: mkstemp(%s)", __FUNCTION__, control_path);
305 control_file = fdopen(fd, "r+");
306 if (control_file == NULL) {
307 perror_msg("%s: fdopen", __FUNCTION__, control_path);
313 err = pkg_extract_control_file_to_stream(pkg, control_file);
317 rewind(control_file);
318 pkg_parse_from_stream(pkg, control_file, PFM_ALL);
321 fclose(control_file);
323 unlink(control_path);
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. */
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
338 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
340 if (oldpkg == newpkg) {
344 if (!oldpkg->auto_installed)
345 oldpkg->auto_installed = newpkg->auto_installed;
348 oldpkg->src = newpkg->src;
350 oldpkg->dest = newpkg->dest;
351 if (!oldpkg->architecture)
352 oldpkg->architecture = xstrdup(newpkg->architecture);
353 if (!oldpkg->arch_priority)
354 oldpkg->arch_priority = newpkg->arch_priority;
355 if (!oldpkg->section)
356 oldpkg->section = xstrdup(newpkg->section);
357 if(!oldpkg->maintainer)
358 oldpkg->maintainer = xstrdup(newpkg->maintainer);
359 if(!oldpkg->description)
360 oldpkg->description = xstrdup(newpkg->description);
362 /* merge the state_flags from the new package */
363 oldpkg->state_want = newpkg->state_want;
364 oldpkg->state_status = newpkg->state_status;
365 oldpkg->state_flag = newpkg->state_flag;
367 if (oldpkg->state_want == SW_UNKNOWN)
368 oldpkg->state_want = newpkg->state_want;
369 if (oldpkg->state_status == SS_NOT_INSTALLED)
370 oldpkg->state_status = newpkg->state_status;
371 oldpkg->state_flag |= newpkg->state_flag;
374 if (!oldpkg->depends_count && !oldpkg->pre_depends_count && !oldpkg->recommends_count && !oldpkg->suggests_count) {
375 oldpkg->depends_count = newpkg->depends_count;
376 newpkg->depends_count = 0;
378 oldpkg->depends = newpkg->depends;
379 newpkg->depends = NULL;
381 oldpkg->pre_depends_count = newpkg->pre_depends_count;
382 newpkg->pre_depends_count = 0;
384 oldpkg->recommends_count = newpkg->recommends_count;
385 newpkg->recommends_count = 0;
387 oldpkg->suggests_count = newpkg->suggests_count;
388 newpkg->suggests_count = 0;
391 if (oldpkg->provides_count <= 1) {
392 oldpkg->provides_count = newpkg->provides_count;
393 newpkg->provides_count = 0;
395 if (!oldpkg->provides) {
396 oldpkg->provides = newpkg->provides;
397 newpkg->provides = NULL;
401 if (!oldpkg->conflicts_count) {
402 oldpkg->conflicts_count = newpkg->conflicts_count;
403 newpkg->conflicts_count = 0;
405 oldpkg->conflicts = newpkg->conflicts;
406 newpkg->conflicts = NULL;
409 if (!oldpkg->replaces_count) {
410 oldpkg->replaces_count = newpkg->replaces_count;
411 newpkg->replaces_count = 0;
413 oldpkg->replaces = newpkg->replaces;
414 newpkg->replaces = NULL;
417 if (!oldpkg->filename)
418 oldpkg->filename = xstrdup(newpkg->filename);
419 if (!oldpkg->local_filename)
420 oldpkg->local_filename = xstrdup(newpkg->local_filename);
421 if (!oldpkg->tmp_unpack_dir)
422 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
424 oldpkg->md5sum = xstrdup(newpkg->md5sum);
425 #if defined HAVE_SHA256
426 if (!oldpkg->sha256sum)
427 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
430 oldpkg->size = xstrdup(newpkg->size);
431 if (!oldpkg->installed_size)
432 oldpkg->installed_size = xstrdup(newpkg->installed_size);
433 if (!oldpkg->priority)
434 oldpkg->priority = xstrdup(newpkg->priority);
436 oldpkg->source = xstrdup(newpkg->source);
437 if (nv_pair_list_empty(&oldpkg->conffiles)){
438 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
439 conffile_list_init(&newpkg->conffiles);
441 if (!oldpkg->installed_files){
442 oldpkg->installed_files = newpkg->installed_files;
443 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
444 newpkg->installed_files = NULL;
446 if (!oldpkg->essential)
447 oldpkg->essential = newpkg->essential;
452 abstract_pkg_t *abstract_pkg_new(void)
454 abstract_pkg_t * ab_pkg;
456 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
458 if (ab_pkg == NULL) {
459 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
463 if ( abstract_pkg_init(ab_pkg) < 0 )
469 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
471 ab_pkg->provided_by = abstract_pkg_vec_alloc();
472 if (ab_pkg->provided_by==NULL){
475 ab_pkg->dependencies_checked = 0;
476 ab_pkg->state_status = SS_NOT_INSTALLED;
481 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
485 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
487 fp = fopen(file_name, "r");
489 opkg_message(conf, OPKG_ERROR, "fopen(%s): %s\n",
490 file_name, strerror(errno));
497 if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
498 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
506 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
510 int depends_count = pkg->pre_depends_count +
512 pkg->recommends_count +
515 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
516 goto UNKNOWN_FMT_FIELD;
523 if (strcasecmp(field, "Architecture") == 0) {
524 if (pkg->architecture) {
525 fprintf(fp, "Architecture: %s\n", pkg->architecture);
527 } else if (strcasecmp(field, "Auto-Installed") == 0) {
528 if (pkg->auto_installed)
529 fprintf(fp, "Auto-Installed: yes\n");
531 goto UNKNOWN_FMT_FIELD;
536 if (strcasecmp(field, "Conffiles") == 0) {
537 conffile_list_elt_t *iter;
539 if (nv_pair_list_empty(&pkg->conffiles))
542 fprintf(fp, "Conffiles:\n");
543 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
544 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
545 fprintf(fp, " %s %s\n",
546 ((conffile_t *)iter->data)->name,
547 ((conffile_t *)iter->data)->value);
550 } else if (strcasecmp(field, "Conflicts") == 0) {
552 if (pkg->conflicts_count) {
553 fprintf(fp, "Conflicts:");
554 for(i = 0; i < pkg->conflicts_count; i++) {
555 cdep = pkg->conflicts[i].possibilities[0];
556 fprintf(fp, "%s %s", i == 0 ? "" : ",",
559 fprintf(fp, " (%s%s)",
560 constraint_to_str(cdep->constraint),
567 goto UNKNOWN_FMT_FIELD;
572 if (strcasecmp(field, "Depends") == 0) {
573 if (pkg->depends_count) {
574 fprintf(fp, "Depends:");
575 for (j=0, i=0; i<depends_count; i++) {
576 if (pkg->depends[i].type != DEPEND)
578 str = pkg_depend_str(pkg, i);
579 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
585 } else if (strcasecmp(field, "Description") == 0) {
586 if (pkg->description) {
587 fprintf(fp, "Description: %s\n", pkg->description);
590 goto UNKNOWN_FMT_FIELD;
595 if (pkg->essential) {
596 fprintf(fp, "Essential: yes\n");
602 fprintf(fp, "Filename: %s\n", pkg->filename);
607 if (strcasecmp(field, "Installed-Size") == 0) {
608 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
609 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
610 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
615 if (strcasecmp(field, "Maintainer") == 0) {
616 if (pkg->maintainer) {
617 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
619 } else if (strcasecmp(field, "MD5sum") == 0) {
621 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
624 goto UNKNOWN_FMT_FIELD;
629 if (strcasecmp(field, "Package") == 0) {
630 fprintf(fp, "Package: %s\n", pkg->name);
631 } else if (strcasecmp(field, "Priority") == 0) {
632 fprintf(fp, "Priority: %s\n", pkg->priority);
633 } else if (strcasecmp(field, "Provides") == 0) {
634 if (pkg->provides_count) {
635 fprintf(fp, "Provides:");
636 for(i = 1; i < pkg->provides_count; i++) {
637 fprintf(fp, "%s %s", i == 1 ? "" : ",",
638 pkg->provides[i]->name);
643 goto UNKNOWN_FMT_FIELD;
648 if (strcasecmp (field, "Replaces") == 0) {
649 if (pkg->replaces_count) {
650 fprintf(fp, "Replaces:");
651 for (i = 0; i < pkg->replaces_count; i++) {
652 fprintf(fp, "%s %s", i == 0 ? "" : ",",
653 pkg->replaces[i]->name);
657 } else if (strcasecmp (field, "Recommends") == 0) {
658 if (pkg->recommends_count) {
659 fprintf(fp, "Recommends:");
660 for (j=0, i=0; i<depends_count; i++) {
661 if (pkg->depends[i].type != RECOMMEND)
663 str = pkg_depend_str(pkg, i);
664 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
671 goto UNKNOWN_FMT_FIELD;
676 if (strcasecmp(field, "Section") == 0) {
678 fprintf(fp, "Section: %s\n", pkg->section);
680 #if defined HAVE_SHA256
681 } else if (strcasecmp(field, "SHA256sum") == 0) {
682 if (pkg->sha256sum) {
683 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
686 } else if (strcasecmp(field, "Size") == 0) {
688 fprintf(fp, "Size: %s\n", pkg->size);
690 } else if (strcasecmp(field, "Source") == 0) {
692 fprintf(fp, "Source: %s\n", pkg->source);
694 } else if (strcasecmp(field, "Status") == 0) {
695 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
696 char *pstat = pkg_state_status_to_str(pkg->state_status);
697 char *pwant = pkg_state_want_to_str(pkg->state_want);
699 if (pflag == NULL || pstat == NULL || pwant == NULL)
702 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
707 } else if (strcasecmp(field, "Suggests") == 0) {
708 if (pkg->suggests_count) {
709 fprintf(fp, "Suggests:");
710 for (j=0, i=0; i<depends_count; i++) {
711 if (pkg->depends[i].type != SUGGEST)
713 str = pkg_depend_str(pkg, i);
714 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
721 goto UNKNOWN_FMT_FIELD;
726 if (strcasecmp(field, "Tags") == 0) {
728 fprintf(fp, "Tags: %s\n", pkg->tags);
735 char *version = pkg_version_str_alloc(pkg);
738 fprintf(fp, "Version: %s\n", version);
743 goto UNKNOWN_FMT_FIELD;
749 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
752 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
754 pkg_formatted_field(fp, pkg, "Package");
755 pkg_formatted_field(fp, pkg, "Version");
756 pkg_formatted_field(fp, pkg, "Depends");
757 pkg_formatted_field(fp, pkg, "Recommends");
758 pkg_formatted_field(fp, pkg, "Suggests");
759 pkg_formatted_field(fp, pkg, "Provides");
760 pkg_formatted_field(fp, pkg, "Replaces");
761 pkg_formatted_field(fp, pkg, "Conflicts");
762 pkg_formatted_field(fp, pkg, "Status");
763 pkg_formatted_field(fp, pkg, "Section");
764 pkg_formatted_field(fp, pkg, "Essential");
765 pkg_formatted_field(fp, pkg, "Architecture");
766 pkg_formatted_field(fp, pkg, "Maintainer");
767 pkg_formatted_field(fp, pkg, "MD5sum");
768 pkg_formatted_field(fp, pkg, "Size");
769 pkg_formatted_field(fp, pkg, "Filename");
770 pkg_formatted_field(fp, pkg, "Conffiles");
771 pkg_formatted_field(fp, pkg, "Source");
772 pkg_formatted_field(fp, pkg, "Description");
773 pkg_formatted_field(fp, pkg, "Installed-Time");
774 pkg_formatted_field(fp, pkg, "Tags");
778 void pkg_print_status(pkg_t * pkg, FILE * file)
784 /* XXX: QUESTION: Do we actually want more fields here? The
785 original idea was to save space by installing only what was
786 needed for actual computation, (package, version, status,
787 essential, conffiles). The assumption is that all other fields
788 can be found in th available file.
790 But, someone proposed the idea to make it possible to
791 reconstruct a .opk from an installed package, (ie. for beaming
792 from one handheld to another). So, maybe we actually want a few
793 more fields here, (depends, suggests, etc.), so that that would
794 be guaranteed to work even in the absence of more information
795 from the available file.
797 28-MAR-03: kergoth and I discussed this yesterday. We think
798 the essential info needs to be here for all installed packages
799 because they may not appear in the Packages files on various
800 feeds. Furthermore, one should be able to install from URL or
801 local storage without requiring a Packages file from any feed.
804 pkg_formatted_field(file, pkg, "Package");
805 pkg_formatted_field(file, pkg, "Version");
806 pkg_formatted_field(file, pkg, "Depends");
807 pkg_formatted_field(file, pkg, "Recommends");
808 pkg_formatted_field(file, pkg, "Suggests");
809 pkg_formatted_field(file, pkg, "Provides");
810 pkg_formatted_field(file, pkg, "Replaces");
811 pkg_formatted_field(file, pkg, "Conflicts");
812 pkg_formatted_field(file, pkg, "Status");
813 pkg_formatted_field(file, pkg, "Essential");
814 pkg_formatted_field(file, pkg, "Architecture");
815 pkg_formatted_field(file, pkg, "Conffiles");
816 pkg_formatted_field(file, pkg, "Installed-Time");
817 pkg_formatted_field(file, pkg, "Auto-Installed");
822 * libdpkg - Debian packaging suite library routines
823 * vercmp.c - comparison of version numbers
825 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
827 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
831 if (pkg->epoch > ref_pkg->epoch) {
835 if (pkg->epoch < ref_pkg->epoch) {
839 r = verrevcmp(pkg->version, ref_pkg->version);
844 r = verrevcmp(pkg->revision, ref_pkg->revision);
852 /* assume ascii; warning: evaluates x multiple times! */
853 #define order(x) ((x) == '~' ? -1 \
856 : isalpha((x)) ? (x) \
859 static int verrevcmp(const char *val, const char *ref) {
863 while (*val || *ref) {
866 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
867 int vc= order(*val), rc= order(*ref);
868 if (vc != rc) return vc - rc;
872 while ( *val == '0' ) val++;
873 while ( *ref == '0' ) ref++;
874 while (isdigit(*val) && isdigit(*ref)) {
875 if (!first_diff) first_diff= *val - *ref;
878 if (isdigit(*val)) return 1;
879 if (isdigit(*ref)) return -1;
880 if (first_diff) return first_diff;
885 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
889 r = pkg_compare_versions(it, ref);
891 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
895 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
899 if (strcmp(op, "<<") == 0) {
903 if (strcmp(op, ">>") == 0) {
907 if (strcmp(op, "=") == 0) {
911 fprintf(stderr, "unknown operator: %s", op);
915 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
917 const pkg_t *a = *(const pkg_t**) p1;
918 const pkg_t *b = *(const pkg_t**) p2;
921 if (!a->name || !b->name) {
922 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
923 a, a->name, b, b->name);
927 namecmp = strcmp(a->name, b->name);
930 vercmp = pkg_compare_versions(a, b);
933 if (!a->arch_priority || !b->arch_priority) {
934 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
935 a, a->arch_priority, b, b->arch_priority);
938 if (a->arch_priority > b->arch_priority)
940 if (a->arch_priority < b->arch_priority)
945 int abstract_pkg_name_compare(const void *p1, const void *p2)
947 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
948 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
949 if (!a->name || !b->name) {
950 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
951 a, a->name, b, b->name);
954 return strcmp(a->name, b->name);
959 pkg_version_str_alloc(pkg_t *pkg)
965 sprintf_alloc(&version, "%d:%s-%s",
966 pkg->epoch, pkg->version, pkg->revision);
968 sprintf_alloc(&version, "%d:%s",
969 pkg->epoch, pkg->version);
972 sprintf_alloc(&version, "%s-%s",
973 pkg->version, pkg->revision);
975 version = xstrdup(pkg->version);
982 * XXX: this should be broken into two functions
984 str_list_t *pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
987 char *list_file_name = NULL;
988 FILE *list_file = NULL;
990 char *installed_file_name;
993 pkg->installed_files_ref_cnt++;
995 if (pkg->installed_files) {
996 return pkg->installed_files;
999 pkg->installed_files = str_list_alloc();
1001 /* For uninstalled packages, get the file list directly from the package.
1002 For installed packages, look at the package.list file in the database.
1004 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1005 if (pkg->local_filename == NULL) {
1006 return pkg->installed_files;
1008 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1009 file. In other words, change deb_extract so that it can
1010 simply return the file list as a char *[] rather than
1011 insisting on writing in to a FILE * as it does now. */
1012 sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
1013 conf->tmp_dir, pkg->name);
1014 fd = mkstemp(list_file_name);
1016 opkg_message(conf, OPKG_ERROR, "%s: mkstemp(%s): %s",
1017 __FUNCTION__, list_file_name, strerror(errno));
1018 free(list_file_name);
1019 return pkg->installed_files;
1021 list_file = fdopen(fd, "r+");
1022 if (list_file == NULL) {
1023 opkg_message(conf, OPKG_ERROR, "%s: fdopen: %s",
1024 __FUNCTION__, strerror(errno));
1026 unlink(list_file_name);
1027 free(list_file_name);
1028 return pkg->installed_files;
1030 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1032 opkg_message(conf, OPKG_ERROR, "%s: Error extracting file list "
1033 "from %s: %s\n", __FUNCTION__,
1034 pkg->local_filename, strerror(err));
1036 unlink(list_file_name);
1037 free(list_file_name);
1038 return pkg->installed_files;
1042 sprintf_alloc(&list_file_name, "%s/%s.list",
1043 pkg->dest->info_dir, pkg->name);
1044 list_file = fopen(list_file_name, "r");
1045 if (list_file == NULL) {
1046 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
1047 __FUNCTION__, list_file_name, strerror(errno));
1048 free(list_file_name);
1049 return pkg->installed_files;
1051 free(list_file_name);
1054 if (conf->offline_root)
1055 rootdirlen = strlen(conf->offline_root);
1060 line = file_read_line_alloc(list_file);
1067 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1068 if (*file_name == '.') {
1071 if (*file_name == '/') {
1074 sprintf_alloc(&installed_file_name, "%s%s",
1075 pkg->dest->root_dir, file_name);
1077 if (conf->offline_root &&
1078 strncmp(conf->offline_root, file_name, rootdirlen)) {
1079 sprintf_alloc(&installed_file_name, "%s%s",
1080 conf->offline_root, file_name);
1082 // already contains root_dir as header -> ABSOLUTE
1083 sprintf_alloc(&installed_file_name, "%s", file_name);
1086 str_list_append(pkg->installed_files, installed_file_name);
1087 free(installed_file_name);
1093 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1094 unlink(list_file_name);
1095 free(list_file_name);
1098 return pkg->installed_files;
1101 /* XXX: CLEANUP: This function and it's counterpart,
1102 (pkg_get_installed_files), do not match our init/deinit naming
1103 convention. Nor the alloc/free convention. But, then again, neither
1104 of these conventions currrently fit the way these two functions
1106 int pkg_free_installed_files(pkg_t *pkg)
1108 pkg->installed_files_ref_cnt--;
1110 if (pkg->installed_files_ref_cnt > 0)
1113 if (pkg->installed_files) {
1114 str_list_purge(pkg->installed_files);
1117 pkg->installed_files = NULL;
1122 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1125 char *list_file_name;
1127 //I don't think pkg_free_installed_files should be called here. Jamey
1128 //pkg_free_installed_files(pkg);
1130 sprintf_alloc(&list_file_name, "%s/%s.list",
1131 pkg->dest->info_dir, pkg->name);
1132 if (!conf->noaction) {
1133 err = unlink(list_file_name);
1134 free(list_file_name);
1143 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1145 conffile_list_elt_t *iter;
1146 conffile_t *conffile;
1152 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1153 conffile = (conffile_t *)iter->data;
1155 if (strcmp(conffile->name, file_name) == 0) {
1163 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1164 const char *script, const char *args)
1173 /* XXX: CLEANUP: There must be a better way to handle maintainer
1174 scripts when running with offline_root mode and/or a dest other
1175 than '/'. I've been playing around with some clever chroot
1176 tricks and I might come up with something workable. */
1178 * Attempt to provide a restricted environment for offline operation
1179 * Need the following set as a minimum:
1180 * OPKG_OFFLINE_ROOT = absolute path to root dir
1181 * D = absolute path to root dir (for OE generated postinst)
1182 * PATH = something safe (a restricted set of utilities)
1185 if (conf->offline_root) {
1186 if (conf->offline_root_path) {
1187 setenv("PATH", conf->offline_root_path, 1);
1189 opkg_message(conf, OPKG_NOTICE,
1190 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1193 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1194 setenv("D", conf->offline_root, 1);
1197 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1198 maintainer script within a chroot environment. */
1200 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1201 have scripts in pkg->tmp_unpack_dir. */
1202 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1203 if (pkg->dest == NULL) {
1204 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1205 __FUNCTION__, pkg->name);
1208 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1210 if (pkg->tmp_unpack_dir == NULL) {
1211 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1212 __FUNCTION__, pkg->name);
1215 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1218 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1221 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1223 if (! file_exists(path)) {
1228 sprintf_alloc(&cmd, "%s %s", path, args);
1231 const char *argv[] = {"sh", "-c", cmd, NULL};
1232 err = xsystem(argv);
1237 fprintf(stderr, "%s script returned status %d\n", script, err);
1244 char *pkg_state_want_to_str(pkg_state_want_t sw)
1248 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1249 if (pkg_state_want_map[i].value == sw) {
1250 return xstrdup(pkg_state_want_map[i].str);
1254 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1256 return xstrdup("<STATE_WANT_UNKNOWN>");
1259 pkg_state_want_t pkg_state_want_from_str(char *str)
1263 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1264 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1265 return pkg_state_want_map[i].value;
1269 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1274 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1277 int len = 3; /* ok\000 is minimum */
1280 /* clear the temporary flags before converting to string */
1281 sf &= SF_NONVOLATILE_FLAGS;
1284 return xstrdup("ok");
1287 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1288 if (sf & pkg_state_flag_map[i].value) {
1289 len += strlen(pkg_state_flag_map[i].str) + 1;
1294 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1295 if (sf & pkg_state_flag_map[i].value) {
1296 strcat(str, pkg_state_flag_map[i].str);
1301 str[len-1] = 0; /* squash last comma */
1306 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1311 if (strcmp(str, "ok") == 0) {
1314 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1315 const char *sfname = pkg_state_flag_map[i].str;
1316 int sfname_len = strlen(sfname);
1317 if (strncmp(str, sfname, sfname_len) == 0) {
1318 sf |= pkg_state_flag_map[i].value;
1320 if (str[0] == ',') {
1331 char *pkg_state_status_to_str(pkg_state_status_t ss)
1335 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1336 if (pkg_state_status_map[i].value == ss) {
1337 return xstrdup(pkg_state_status_map[i].str);
1341 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1343 return xstrdup("<STATE_STATUS_UNKNOWN>");
1346 pkg_state_status_t pkg_state_status_from_str(const char *str)
1350 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1351 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1352 return pkg_state_status_map[i].value;
1356 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1358 return SS_NOT_INSTALLED;
1361 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1363 nv_pair_list_elt_t *l;
1365 if (!pkg->architecture)
1368 list_for_each_entry(l , &conf->arch_list.head, node) {
1369 nv_pair_t *nv = (nv_pair_t *)l->data;
1370 if (strcmp(nv->name, pkg->architecture) == 0) {
1371 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1376 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1380 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1382 nv_pair_list_elt_t *l;
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);
1394 int pkg_info_preinstall_check(opkg_conf_t *conf)
1397 hash_table_t *pkg_hash = &conf->pkg_hash;
1398 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1399 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1401 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1402 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1403 /* update arch_priority for each package */
1404 for (i = 0; i < available_pkgs->len; i++) {
1405 pkg_t *pkg = available_pkgs->pkgs[i];
1406 int arch_priority = 1;
1409 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1410 if (pkg->architecture)
1411 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1413 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1414 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1415 pkg->arch_priority = arch_priority;
1418 for (i = 0; i < available_pkgs->len; i++) {
1419 pkg_t *pkg = available_pkgs->pkgs[i];
1420 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1421 /* clear flags and want for any uninstallable package */
1422 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1423 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1424 pkg->state_want = SW_UNKNOWN;
1425 pkg->state_flag = 0;
1428 pkg_vec_free(available_pkgs);
1430 /* update the file owner data structure */
1431 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1432 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1433 for (i = 0; i < installed_pkgs->len; i++) {
1434 pkg_t *pkg = installed_pkgs->pkgs[i];
1435 str_list_t *installed_files = pkg_get_installed_files(conf, pkg); /* this causes installed_files to be cached */
1436 str_list_elt_t *iter, *niter;
1437 if (installed_files == NULL) {
1438 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1441 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1443 iter = niter, niter = str_list_next(installed_files, iter)) {
1444 char *installed_file = (char *) iter->data;
1445 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1446 file_hash_set_file_owner(conf, installed_file, pkg);
1448 pkg_free_installed_files(pkg);
1450 pkg_vec_free(installed_pkgs);
1455 struct pkg_write_filelist_data {
1461 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
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);
1470 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1472 struct pkg_write_filelist_data data;
1473 char *list_file_name = NULL;
1477 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1480 opkg_message(conf, OPKG_INFO,
1481 " creating %s.list file\n", pkg->name);
1482 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1483 if (!list_file_name) {
1484 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1487 opkg_message(conf, OPKG_INFO,
1488 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1489 data.stream = fopen(list_file_name, "w");
1491 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1492 list_file_name, strerror(errno));
1497 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1498 fclose(data.stream);
1499 free(list_file_name);
1501 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1506 int pkg_write_changed_filelists(opkg_conf_t *conf)
1508 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1509 hash_table_t *pkg_hash = &conf->pkg_hash;
1515 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
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 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1521 err = pkg_write_filelist(conf, pkg);
1523 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1526 pkg_vec_free (installed_pkgs);