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;
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;
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;
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;
222 int count = pkg->pre_depends_count
224 + pkg->recommends_count
225 + pkg->suggests_count;
227 for (i=0; i<count; i++)
228 compound_depend_deinit (&pkg->depends[i]);
232 if (pkg->conflicts) {
233 for (i=0; i<pkg->conflicts_count; i++)
234 compound_depend_deinit (&pkg->conflicts[i]);
235 free (pkg->conflicts);
239 free (pkg->provides);
241 pkg->pre_depends_count = 0;
242 if (pkg->pre_depends_str)
243 free(pkg->pre_depends_str);
244 pkg->pre_depends_str = NULL;
246 pkg->provides_count = 0;
250 pkg->filename = NULL;
252 if (pkg->local_filename)
253 free(pkg->local_filename);
254 pkg->local_filename = NULL;
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;
267 #if defined HAVE_SHA256
269 free(pkg->sha256sum);
270 pkg->sha256sum = NULL;
277 if (pkg->installed_size)
278 free(pkg->installed_size);
279 pkg->installed_size = NULL;
283 pkg->priority = NULL;
289 conffile_list_deinit(&pkg->conffiles);
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);
304 pkg_init_from_file(opkg_conf_t *conf, pkg_t *pkg, const char *filename)
312 pkg->local_filename = xstrdup(filename);
314 sprintf_alloc(&control_path, "%s/%s.control.XXXXXX",
317 fd = mkstemp(control_path);
319 perror_msg("%s: mkstemp(%s)", __FUNCTION__, control_path);
324 control_file = fdopen(fd, "r+");
325 if (control_file == NULL) {
326 perror_msg("%s: fdopen", __FUNCTION__, control_path);
332 err = pkg_extract_control_file_to_stream(pkg, control_file);
336 rewind(control_file);
337 pkg_parse_from_stream(pkg, control_file, PFM_ALL);
340 fclose(control_file);
342 unlink(control_path);
349 /* Merge any new information in newpkg into oldpkg */
350 /* XXX: CLEANUP: This function shouldn't actually modify anything in
351 newpkg, but should leave it usable. This rework is so that
352 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
354 * uh, i thought that i had originally written this so that it took
355 * two pkgs and returned a new one? we can do that again... -sma
357 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
359 if (oldpkg == newpkg) {
363 if (!oldpkg->auto_installed)
364 oldpkg->auto_installed = newpkg->auto_installed;
367 oldpkg->src = newpkg->src;
369 oldpkg->dest = newpkg->dest;
370 if (!oldpkg->architecture)
371 oldpkg->architecture = xstrdup(newpkg->architecture);
372 if (!oldpkg->arch_priority)
373 oldpkg->arch_priority = newpkg->arch_priority;
374 if (!oldpkg->section)
375 oldpkg->section = xstrdup(newpkg->section);
376 if(!oldpkg->maintainer)
377 oldpkg->maintainer = xstrdup(newpkg->maintainer);
378 if(!oldpkg->description)
379 oldpkg->description = xstrdup(newpkg->description);
381 /* merge the state_flags from the new package */
382 oldpkg->state_want = newpkg->state_want;
383 oldpkg->state_status = newpkg->state_status;
384 oldpkg->state_flag = newpkg->state_flag;
386 if (oldpkg->state_want == SW_UNKNOWN)
387 oldpkg->state_want = newpkg->state_want;
388 if (oldpkg->state_status == SS_NOT_INSTALLED)
389 oldpkg->state_status = newpkg->state_status;
390 oldpkg->state_flag |= newpkg->state_flag;
393 if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
394 oldpkg->depends_str = newpkg->depends_str;
395 newpkg->depends_str = NULL;
396 oldpkg->depends_count = newpkg->depends_count;
397 newpkg->depends_count = 0;
399 oldpkg->depends = newpkg->depends;
400 newpkg->depends = NULL;
402 oldpkg->pre_depends_str = newpkg->pre_depends_str;
403 newpkg->pre_depends_str = NULL;
404 oldpkg->pre_depends_count = newpkg->pre_depends_count;
405 newpkg->pre_depends_count = 0;
407 oldpkg->recommends_str = newpkg->recommends_str;
408 newpkg->recommends_str = NULL;
409 oldpkg->recommends_count = newpkg->recommends_count;
410 newpkg->recommends_count = 0;
412 oldpkg->suggests_str = newpkg->suggests_str;
413 newpkg->suggests_str = NULL;
414 oldpkg->suggests_count = newpkg->suggests_count;
415 newpkg->suggests_count = 0;
418 if (oldpkg->provides_count <= 1) {
419 oldpkg->provides_count = newpkg->provides_count;
420 newpkg->provides_count = 0;
422 if (!oldpkg->provides) {
423 oldpkg->provides = newpkg->provides;
424 newpkg->provides = NULL;
428 if (!oldpkg->conflicts_count) {
429 oldpkg->conflicts_count = newpkg->conflicts_count;
430 newpkg->conflicts_count = 0;
432 oldpkg->conflicts = newpkg->conflicts;
433 newpkg->conflicts = NULL;
436 if (!oldpkg->replaces_count) {
437 oldpkg->replaces_count = newpkg->replaces_count;
438 newpkg->replaces_count = 0;
440 oldpkg->replaces = newpkg->replaces;
441 newpkg->replaces = NULL;
444 if (!oldpkg->filename)
445 oldpkg->filename = xstrdup(newpkg->filename);
446 if (!oldpkg->local_filename)
447 oldpkg->local_filename = xstrdup(newpkg->local_filename);
448 if (!oldpkg->tmp_unpack_dir)
449 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
451 oldpkg->md5sum = xstrdup(newpkg->md5sum);
452 #if defined HAVE_SHA256
453 if (!oldpkg->sha256sum)
454 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
457 oldpkg->size = xstrdup(newpkg->size);
458 if (!oldpkg->installed_size)
459 oldpkg->installed_size = xstrdup(newpkg->installed_size);
460 if (!oldpkg->priority)
461 oldpkg->priority = xstrdup(newpkg->priority);
463 oldpkg->source = xstrdup(newpkg->source);
464 if (nv_pair_list_empty(&oldpkg->conffiles)){
465 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
466 conffile_list_init(&newpkg->conffiles);
468 if (!oldpkg->installed_files){
469 oldpkg->installed_files = newpkg->installed_files;
470 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
471 newpkg->installed_files = NULL;
473 if (!oldpkg->essential)
474 oldpkg->essential = newpkg->essential;
479 abstract_pkg_t *abstract_pkg_new(void)
481 abstract_pkg_t * ab_pkg;
483 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
485 if (ab_pkg == NULL) {
486 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
490 if ( abstract_pkg_init(ab_pkg) < 0 )
496 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
498 ab_pkg->provided_by = abstract_pkg_vec_alloc();
499 if (ab_pkg->provided_by==NULL){
502 ab_pkg->dependencies_checked = 0;
503 ab_pkg->state_status = SS_NOT_INSTALLED;
508 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
512 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
514 fp = fopen(file_name, "r");
516 opkg_message(conf, OPKG_ERROR, "fopen(%s): %s\n",
517 file_name, strerror(errno));
524 if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
525 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
534 constraint_to_str(enum version_constraint c)
554 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
558 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
559 goto UNKNOWN_FMT_FIELD;
566 if (strcasecmp(field, "Architecture") == 0) {
567 if (pkg->architecture) {
568 fprintf(fp, "Architecture: %s\n", pkg->architecture);
570 } else if (strcasecmp(field, "Auto-Installed") == 0) {
571 if (pkg->auto_installed)
572 fprintf(fp, "Auto-Installed: yes\n");
574 goto UNKNOWN_FMT_FIELD;
579 if (strcasecmp(field, "Conffiles") == 0) {
580 conffile_list_elt_t *iter;
582 if (nv_pair_list_empty(&pkg->conffiles))
585 fprintf(fp, "Conffiles:\n");
586 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
587 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
588 fprintf(fp, " %s %s\n",
589 ((conffile_t *)iter->data)->name,
590 ((conffile_t *)iter->data)->value);
593 } else if (strcasecmp(field, "Conflicts") == 0) {
595 if (pkg->conflicts_count) {
596 fprintf(fp, "Conflicts:");
597 for(i = 0; i < pkg->conflicts_count; i++) {
598 cdep = pkg->conflicts[i].possibilities[0];
599 fprintf(fp, "%s %s", i == 0 ? "" : ",",
602 fprintf(fp, "(%s%s)",
603 constraint_to_str(cdep->constraint),
610 goto UNKNOWN_FMT_FIELD;
615 if (strcasecmp(field, "Depends") == 0) {
616 if (pkg->depends_count) {
617 fprintf(fp, "Depends:");
618 for(i = 0; i < pkg->depends_count; i++) {
619 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
623 } else if (strcasecmp(field, "Description") == 0) {
624 if (pkg->description) {
625 fprintf(fp, "Description: %s\n", pkg->description);
628 goto UNKNOWN_FMT_FIELD;
633 if (pkg->essential) {
634 fprintf(fp, "Essential: yes\n");
640 fprintf(fp, "Filename: %s\n", pkg->filename);
645 if (strcasecmp(field, "Installed-Size") == 0) {
646 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
647 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
648 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
653 if (strcasecmp(field, "Maintainer") == 0) {
654 if (pkg->maintainer) {
655 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
657 } else if (strcasecmp(field, "MD5sum") == 0) {
659 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
662 goto UNKNOWN_FMT_FIELD;
667 if (strcasecmp(field, "Package") == 0) {
668 fprintf(fp, "Package: %s\n", pkg->name);
669 } else if (strcasecmp(field, "Priority") == 0) {
670 fprintf(fp, "Priority: %s\n", pkg->priority);
671 } else if (strcasecmp(field, "Provides") == 0) {
672 if (pkg->provides_count) {
673 fprintf(fp, "Provides:");
674 for(i = 1; i < pkg->provides_count; i++) {
675 fprintf(fp, "%s %s", i == 1 ? "" : ",",
676 pkg->provides[i]->name);
681 goto UNKNOWN_FMT_FIELD;
686 if (strcasecmp (field, "Replaces") == 0) {
687 if (pkg->replaces_count) {
688 fprintf(fp, "Replaces:");
689 for (i = 0; i < pkg->replaces_count; i++) {
690 fprintf(fp, "%s %s", i == 0 ? "" : ",",
691 pkg->replaces[i]->name);
695 } else if (strcasecmp (field, "Recommends") == 0) {
696 if (pkg->recommends_count) {
697 fprintf(fp, "Recommends:");
698 for(i = 0; i < pkg->recommends_count; i++) {
699 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
704 goto UNKNOWN_FMT_FIELD;
709 if (strcasecmp(field, "Section") == 0) {
711 fprintf(fp, "Section: %s\n", pkg->section);
713 #if defined HAVE_SHA256
714 } else if (strcasecmp(field, "SHA256sum") == 0) {
715 if (pkg->sha256sum) {
716 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
719 } else if (strcasecmp(field, "Size") == 0) {
721 fprintf(fp, "Size: %s\n", pkg->size);
723 } else if (strcasecmp(field, "Source") == 0) {
725 fprintf(fp, "Source: %s\n", pkg->source);
727 } else if (strcasecmp(field, "Status") == 0) {
728 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
729 char *pstat = pkg_state_status_to_str(pkg->state_status);
730 char *pwant = pkg_state_want_to_str(pkg->state_want);
732 if (pflag == NULL || pstat == NULL || pwant == NULL)
735 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
740 } else if (strcasecmp(field, "Suggests") == 0) {
741 if (pkg->suggests_count) {
742 fprintf(fp, "Suggests:");
743 for(i = 0; i < pkg->suggests_count; i++) {
744 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
749 goto UNKNOWN_FMT_FIELD;
754 if (strcasecmp(field, "Tags") == 0) {
756 fprintf(fp, "Tags: %s\n", pkg->tags);
763 char *version = pkg_version_str_alloc(pkg);
766 fprintf(fp, "Version: %s\n", version);
771 goto UNKNOWN_FMT_FIELD;
777 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
780 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
782 pkg_formatted_field(fp, pkg, "Package");
783 pkg_formatted_field(fp, pkg, "Version");
784 pkg_formatted_field(fp, pkg, "Depends");
785 pkg_formatted_field(fp, pkg, "Recommends");
786 pkg_formatted_field(fp, pkg, "Suggests");
787 pkg_formatted_field(fp, pkg, "Provides");
788 pkg_formatted_field(fp, pkg, "Replaces");
789 pkg_formatted_field(fp, pkg, "Conflicts");
790 pkg_formatted_field(fp, pkg, "Status");
791 pkg_formatted_field(fp, pkg, "Section");
792 pkg_formatted_field(fp, pkg, "Essential");
793 pkg_formatted_field(fp, pkg, "Architecture");
794 pkg_formatted_field(fp, pkg, "Maintainer");
795 pkg_formatted_field(fp, pkg, "MD5sum");
796 pkg_formatted_field(fp, pkg, "Size");
797 pkg_formatted_field(fp, pkg, "Filename");
798 pkg_formatted_field(fp, pkg, "Conffiles");
799 pkg_formatted_field(fp, pkg, "Source");
800 pkg_formatted_field(fp, pkg, "Description");
801 pkg_formatted_field(fp, pkg, "Installed-Time");
802 pkg_formatted_field(fp, pkg, "Tags");
806 void pkg_print_status(pkg_t * pkg, FILE * file)
812 /* XXX: QUESTION: Do we actually want more fields here? The
813 original idea was to save space by installing only what was
814 needed for actual computation, (package, version, status,
815 essential, conffiles). The assumption is that all other fields
816 can be found in th available file.
818 But, someone proposed the idea to make it possible to
819 reconstruct a .opk from an installed package, (ie. for beaming
820 from one handheld to another). So, maybe we actually want a few
821 more fields here, (depends, suggests, etc.), so that that would
822 be guaranteed to work even in the absence of more information
823 from the available file.
825 28-MAR-03: kergoth and I discussed this yesterday. We think
826 the essential info needs to be here for all installed packages
827 because they may not appear in the Packages files on various
828 feeds. Furthermore, one should be able to install from URL or
829 local storage without requiring a Packages file from any feed.
832 pkg_formatted_field(file, pkg, "Package");
833 pkg_formatted_field(file, pkg, "Version");
834 pkg_formatted_field(file, pkg, "Depends");
835 pkg_formatted_field(file, pkg, "Recommends");
836 pkg_formatted_field(file, pkg, "Suggests");
837 pkg_formatted_field(file, pkg, "Provides");
838 pkg_formatted_field(file, pkg, "Replaces");
839 pkg_formatted_field(file, pkg, "Conflicts");
840 pkg_formatted_field(file, pkg, "Status");
841 pkg_formatted_field(file, pkg, "Essential");
842 pkg_formatted_field(file, pkg, "Architecture");
843 pkg_formatted_field(file, pkg, "Conffiles");
844 pkg_formatted_field(file, pkg, "Installed-Time");
845 pkg_formatted_field(file, pkg, "Auto-Installed");
850 * libdpkg - Debian packaging suite library routines
851 * vercmp.c - comparison of version numbers
853 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
855 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
859 if (pkg->epoch > ref_pkg->epoch) {
863 if (pkg->epoch < ref_pkg->epoch) {
867 r = verrevcmp(pkg->version, ref_pkg->version);
872 r = verrevcmp(pkg->revision, ref_pkg->revision);
880 /* assume ascii; warning: evaluates x multiple times! */
881 #define order(x) ((x) == '~' ? -1 \
884 : isalpha((x)) ? (x) \
887 static int verrevcmp(const char *val, const char *ref) {
891 while (*val || *ref) {
894 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
895 int vc= order(*val), rc= order(*ref);
896 if (vc != rc) return vc - rc;
900 while ( *val == '0' ) val++;
901 while ( *ref == '0' ) ref++;
902 while (isdigit(*val) && isdigit(*ref)) {
903 if (!first_diff) first_diff= *val - *ref;
906 if (isdigit(*val)) return 1;
907 if (isdigit(*ref)) return -1;
908 if (first_diff) return first_diff;
913 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
917 r = pkg_compare_versions(it, ref);
919 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
923 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
927 if (strcmp(op, "<<") == 0) {
931 if (strcmp(op, ">>") == 0) {
935 if (strcmp(op, "=") == 0) {
939 fprintf(stderr, "unknown operator: %s", op);
943 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
945 const pkg_t *a = *(const pkg_t**) p1;
946 const pkg_t *b = *(const pkg_t**) p2;
949 if (!a->name || !b->name) {
950 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
951 a, a->name, b, b->name);
955 namecmp = strcmp(a->name, b->name);
958 vercmp = pkg_compare_versions(a, b);
961 if (!a->arch_priority || !b->arch_priority) {
962 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
963 a, a->arch_priority, b, b->arch_priority);
966 if (a->arch_priority > b->arch_priority)
968 if (a->arch_priority < b->arch_priority)
973 int abstract_pkg_name_compare(const void *p1, const void *p2)
975 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
976 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
977 if (!a->name || !b->name) {
978 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
979 a, a->name, b, b->name);
982 return strcmp(a->name, b->name);
987 pkg_version_str_alloc(pkg_t *pkg)
993 sprintf_alloc(&version, "%d:%s-%s",
994 pkg->epoch, pkg->version, pkg->revision);
996 sprintf_alloc(&version, "%d:%s",
997 pkg->epoch, pkg->version);
1000 sprintf_alloc(&version, "%s-%s",
1001 pkg->version, pkg->revision);
1003 version = xstrdup(pkg->version);
1010 * XXX: this should be broken into two functions
1012 str_list_t *pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
1015 char *list_file_name = NULL;
1016 FILE *list_file = NULL;
1018 char *installed_file_name;
1021 pkg->installed_files_ref_cnt++;
1023 if (pkg->installed_files) {
1024 return pkg->installed_files;
1027 pkg->installed_files = str_list_alloc();
1029 /* For uninstalled packages, get the file list directly from the package.
1030 For installed packages, look at the package.list file in the database.
1032 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1033 if (pkg->local_filename == NULL) {
1034 return pkg->installed_files;
1036 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1037 file. In other words, change deb_extract so that it can
1038 simply return the file list as a char *[] rather than
1039 insisting on writing in to a FILE * as it does now. */
1040 sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
1041 conf->tmp_dir, pkg->name);
1042 fd = mkstemp(list_file_name);
1044 opkg_message(conf, OPKG_ERROR, "%s: mkstemp(%s): %s",
1045 __FUNCTION__, list_file_name, strerror(errno));
1046 free(list_file_name);
1047 return pkg->installed_files;
1049 list_file = fdopen(fd, "r+");
1050 if (list_file == NULL) {
1051 opkg_message(conf, OPKG_ERROR, "%s: fdopen: %s",
1052 __FUNCTION__, strerror(errno));
1054 unlink(list_file_name);
1055 free(list_file_name);
1056 return pkg->installed_files;
1058 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1060 opkg_message(conf, OPKG_ERROR, "%s: Error extracting file list "
1061 "from %s: %s\n", __FUNCTION__,
1062 pkg->local_filename, strerror(err));
1064 unlink(list_file_name);
1065 free(list_file_name);
1066 return pkg->installed_files;
1070 sprintf_alloc(&list_file_name, "%s/%s.list",
1071 pkg->dest->info_dir, pkg->name);
1072 list_file = fopen(list_file_name, "r");
1073 if (list_file == NULL) {
1074 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
1075 __FUNCTION__, list_file_name, strerror(errno));
1076 free(list_file_name);
1077 return pkg->installed_files;
1079 free(list_file_name);
1082 if (conf->offline_root)
1083 rootdirlen = strlen(conf->offline_root);
1088 line = file_read_line_alloc(list_file);
1095 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1096 if (*file_name == '.') {
1099 if (*file_name == '/') {
1102 sprintf_alloc(&installed_file_name, "%s%s",
1103 pkg->dest->root_dir, file_name);
1105 if (conf->offline_root &&
1106 strncmp(conf->offline_root, file_name, rootdirlen)) {
1107 sprintf_alloc(&installed_file_name, "%s%s",
1108 conf->offline_root, file_name);
1110 // already contains root_dir as header -> ABSOLUTE
1111 sprintf_alloc(&installed_file_name, "%s", file_name);
1114 str_list_append(pkg->installed_files, installed_file_name);
1115 free(installed_file_name);
1121 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1122 unlink(list_file_name);
1123 free(list_file_name);
1126 return pkg->installed_files;
1129 /* XXX: CLEANUP: This function and it's counterpart,
1130 (pkg_get_installed_files), do not match our init/deinit naming
1131 convention. Nor the alloc/free convention. But, then again, neither
1132 of these conventions currrently fit the way these two functions
1134 int pkg_free_installed_files(pkg_t *pkg)
1136 pkg->installed_files_ref_cnt--;
1138 if (pkg->installed_files_ref_cnt > 0)
1141 if (pkg->installed_files) {
1142 str_list_purge(pkg->installed_files);
1145 pkg->installed_files = NULL;
1150 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1153 char *list_file_name;
1155 //I don't think pkg_free_installed_files should be called here. Jamey
1156 //pkg_free_installed_files(pkg);
1158 sprintf_alloc(&list_file_name, "%s/%s.list",
1159 pkg->dest->info_dir, pkg->name);
1160 if (!conf->noaction) {
1161 err = unlink(list_file_name);
1162 free(list_file_name);
1171 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1173 conffile_list_elt_t *iter;
1174 conffile_t *conffile;
1180 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1181 conffile = (conffile_t *)iter->data;
1183 if (strcmp(conffile->name, file_name) == 0) {
1191 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1192 const char *script, const char *args)
1201 /* XXX: CLEANUP: There must be a better way to handle maintainer
1202 scripts when running with offline_root mode and/or a dest other
1203 than '/'. I've been playing around with some clever chroot
1204 tricks and I might come up with something workable. */
1206 * Attempt to provide a restricted environment for offline operation
1207 * Need the following set as a minimum:
1208 * OPKG_OFFLINE_ROOT = absolute path to root dir
1209 * D = absolute path to root dir (for OE generated postinst)
1210 * PATH = something safe (a restricted set of utilities)
1213 if (conf->offline_root) {
1214 if (conf->offline_root_path) {
1215 setenv("PATH", conf->offline_root_path, 1);
1217 opkg_message(conf, OPKG_NOTICE,
1218 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1221 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1222 setenv("D", conf->offline_root, 1);
1225 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1226 maintainer script within a chroot environment. */
1228 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1229 have scripts in pkg->tmp_unpack_dir. */
1230 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1231 if (pkg->dest == NULL) {
1232 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1233 __FUNCTION__, pkg->name);
1236 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1238 if (pkg->tmp_unpack_dir == NULL) {
1239 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1240 __FUNCTION__, pkg->name);
1243 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1246 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1249 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1251 if (! file_exists(path)) {
1256 sprintf_alloc(&cmd, "%s %s", path, args);
1259 const char *argv[] = {"sh", "-c", cmd, NULL};
1260 err = xsystem(argv);
1265 fprintf(stderr, "%s script returned status %d\n", script, err);
1272 char *pkg_state_want_to_str(pkg_state_want_t sw)
1276 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1277 if (pkg_state_want_map[i].value == sw) {
1278 return xstrdup(pkg_state_want_map[i].str);
1282 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1284 return xstrdup("<STATE_WANT_UNKNOWN>");
1287 pkg_state_want_t pkg_state_want_from_str(char *str)
1291 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1292 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1293 return pkg_state_want_map[i].value;
1297 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1302 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1305 int len = 3; /* ok\000 is minimum */
1308 /* clear the temporary flags before converting to string */
1309 sf &= SF_NONVOLATILE_FLAGS;
1312 return xstrdup("ok");
1315 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1316 if (sf & pkg_state_flag_map[i].value) {
1317 len += strlen(pkg_state_flag_map[i].str) + 1;
1322 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1323 if (sf & pkg_state_flag_map[i].value) {
1324 strcat(str, pkg_state_flag_map[i].str);
1329 str[len-1] = 0; /* squash last comma */
1334 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1339 if (strcmp(str, "ok") == 0) {
1342 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1343 const char *sfname = pkg_state_flag_map[i].str;
1344 int sfname_len = strlen(sfname);
1345 if (strncmp(str, sfname, sfname_len) == 0) {
1346 sf |= pkg_state_flag_map[i].value;
1348 if (str[0] == ',') {
1359 char *pkg_state_status_to_str(pkg_state_status_t ss)
1363 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1364 if (pkg_state_status_map[i].value == ss) {
1365 return xstrdup(pkg_state_status_map[i].str);
1369 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1371 return xstrdup("<STATE_STATUS_UNKNOWN>");
1374 pkg_state_status_t pkg_state_status_from_str(const char *str)
1378 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1379 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1380 return pkg_state_status_map[i].value;
1384 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1386 return SS_NOT_INSTALLED;
1389 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1391 nv_pair_list_elt_t *l;
1393 if (!pkg->architecture)
1396 list_for_each_entry(l , &conf->arch_list.head, node) {
1397 nv_pair_t *nv = (nv_pair_t *)l->data;
1398 if (strcmp(nv->name, pkg->architecture) == 0) {
1399 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1404 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1408 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1410 nv_pair_list_elt_t *l;
1412 list_for_each_entry(l , &conf->arch_list.head, node) {
1413 nv_pair_t *nv = (nv_pair_t *)l->data;
1414 if (strcmp(nv->name, archname) == 0) {
1415 int priority = strtol(nv->value, NULL, 0);
1422 int pkg_info_preinstall_check(opkg_conf_t *conf)
1425 hash_table_t *pkg_hash = &conf->pkg_hash;
1426 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1427 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1429 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1430 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1431 /* update arch_priority for each package */
1432 for (i = 0; i < available_pkgs->len; i++) {
1433 pkg_t *pkg = available_pkgs->pkgs[i];
1434 int arch_priority = 1;
1437 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1438 if (pkg->architecture)
1439 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1441 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1442 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1443 pkg->arch_priority = arch_priority;
1446 for (i = 0; i < available_pkgs->len; i++) {
1447 pkg_t *pkg = available_pkgs->pkgs[i];
1448 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1449 /* clear flags and want for any uninstallable package */
1450 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1451 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1452 pkg->state_want = SW_UNKNOWN;
1453 pkg->state_flag = 0;
1456 pkg_vec_free(available_pkgs);
1458 /* update the file owner data structure */
1459 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1460 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1461 for (i = 0; i < installed_pkgs->len; i++) {
1462 pkg_t *pkg = installed_pkgs->pkgs[i];
1463 str_list_t *installed_files = pkg_get_installed_files(conf, pkg); /* this causes installed_files to be cached */
1464 str_list_elt_t *iter, *niter;
1465 if (installed_files == NULL) {
1466 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1469 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1471 iter = niter, niter = str_list_next(installed_files, iter)) {
1472 char *installed_file = (char *) iter->data;
1473 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1474 file_hash_set_file_owner(conf, installed_file, pkg);
1476 pkg_free_installed_files(pkg);
1478 pkg_vec_free(installed_pkgs);
1483 struct pkg_write_filelist_data {
1489 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1491 struct pkg_write_filelist_data *data = data_;
1492 pkg_t *entry = entry_;
1493 if (entry == data->pkg) {
1494 fprintf(data->stream, "%s\n", key);
1498 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1500 struct pkg_write_filelist_data data;
1501 char *list_file_name = NULL;
1505 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1508 opkg_message(conf, OPKG_INFO,
1509 " creating %s.list file\n", pkg->name);
1510 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1511 if (!list_file_name) {
1512 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1515 opkg_message(conf, OPKG_INFO,
1516 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1517 data.stream = fopen(list_file_name, "w");
1519 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1520 list_file_name, strerror(errno));
1525 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1526 fclose(data.stream);
1527 free(list_file_name);
1529 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1534 int pkg_write_changed_filelists(opkg_conf_t *conf)
1536 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1537 hash_table_t *pkg_hash = &conf->pkg_hash;
1543 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1544 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1545 for (i = 0; i < installed_pkgs->len; i++) {
1546 pkg_t *pkg = installed_pkgs->pkgs[i];
1547 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1548 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1549 err = pkg_write_filelist(conf, pkg);
1551 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1554 pkg_vec_free (installed_pkgs);