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(pkg_t *pkg, const char *filename)
312 pkg->local_filename = xstrdup(filename);
314 sprintf_alloc(&control_path, "%s.control.XXXXXX", filename);
315 fd = mkstemp(control_path);
317 perror_msg("%s: mkstemp(%s)", __FUNCTION__, control_path);
322 control_file = fdopen(fd, "rw+");
323 if (control_file == NULL) {
324 perror_msg("%s: fdopen", __FUNCTION__, control_path);
330 err = pkg_extract_control_file_to_stream(pkg, control_file);
334 rewind(control_file);
335 pkg_parse_from_stream(pkg, control_file, PFM_ALL);
338 fclose(control_file);
340 unlink(control_path);
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. */
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
355 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
357 if (oldpkg == newpkg) {
362 oldpkg->src = newpkg->src;
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);
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;
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;
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;
394 oldpkg->depends = newpkg->depends;
395 newpkg->depends = NULL;
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;
402 oldpkg->recommends_str = newpkg->recommends_str;
403 newpkg->recommends_str = NULL;
404 oldpkg->recommends_count = newpkg->recommends_count;
405 newpkg->recommends_count = 0;
407 oldpkg->suggests_str = newpkg->suggests_str;
408 newpkg->suggests_str = NULL;
409 oldpkg->suggests_count = newpkg->suggests_count;
410 newpkg->suggests_count = 0;
413 if (oldpkg->provides_count <= 1) {
414 oldpkg->provides_count = newpkg->provides_count;
415 newpkg->provides_count = 0;
417 if (!oldpkg->provides) {
418 oldpkg->provides = newpkg->provides;
419 newpkg->provides = NULL;
423 if (!oldpkg->conflicts_count) {
424 oldpkg->conflicts_count = newpkg->conflicts_count;
425 newpkg->conflicts_count = 0;
427 oldpkg->conflicts = newpkg->conflicts;
428 newpkg->conflicts = NULL;
431 if (!oldpkg->replaces_count) {
432 oldpkg->replaces_count = newpkg->replaces_count;
433 newpkg->replaces_count = 0;
435 oldpkg->replaces = newpkg->replaces;
436 newpkg->replaces = NULL;
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);
446 oldpkg->md5sum = xstrdup(newpkg->md5sum);
447 #if defined HAVE_SHA256
448 if (!oldpkg->sha256sum)
449 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
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);
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);
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;
468 if (!oldpkg->essential)
469 oldpkg->essential = newpkg->essential;
474 abstract_pkg_t *abstract_pkg_new(void)
476 abstract_pkg_t * ab_pkg;
478 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
480 if (ab_pkg == NULL) {
481 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
485 if ( abstract_pkg_init(ab_pkg) < 0 )
491 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
493 ab_pkg->provided_by = abstract_pkg_vec_alloc();
494 if (ab_pkg->provided_by==NULL){
497 ab_pkg->dependencies_checked = 0;
498 ab_pkg->state_status = SS_NOT_INSTALLED;
503 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
507 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
509 fp = fopen(file_name, "r");
511 opkg_message(conf, OPKG_ERROR, "fopen(%s): %s\n",
512 file_name, strerror(errno));
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);
529 constraint_to_str(enum version_constraint c)
549 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
553 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
554 goto UNKNOWN_FMT_FIELD;
561 if (strcasecmp(field, "Architecture") == 0) {
562 if (pkg->architecture) {
563 fprintf(fp, "Architecture: %s\n", pkg->architecture);
565 } else if (strcasecmp(field, "Auto-Installed") == 0) {
566 if (pkg->auto_installed)
567 fprintf(fp, "Auto-Installed: yes\n");
569 goto UNKNOWN_FMT_FIELD;
574 if (strcasecmp(field, "Conffiles") == 0) {
575 conffile_list_elt_t *iter;
577 if (nv_pair_list_empty(&pkg->conffiles))
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);
588 } else if (strcasecmp(field, "Conflicts") == 0) {
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 ? "" : ",",
597 fprintf(fp, "(%s%s)",
598 constraint_to_str(cdep->constraint),
605 goto UNKNOWN_FMT_FIELD;
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]);
618 } else if (strcasecmp(field, "Description") == 0) {
619 if (pkg->description) {
620 fprintf(fp, "Description: %s\n", pkg->description);
623 goto UNKNOWN_FMT_FIELD;
628 if (pkg->essential) {
629 fprintf(fp, "Essential: yes\n");
635 fprintf(fp, "Filename: %s\n", pkg->filename);
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);
648 if (strcasecmp(field, "Maintainer") == 0) {
649 if (pkg->maintainer) {
650 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
652 } else if (strcasecmp(field, "MD5sum") == 0) {
654 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
657 goto UNKNOWN_FMT_FIELD;
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);
676 goto UNKNOWN_FMT_FIELD;
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);
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]);
699 goto UNKNOWN_FMT_FIELD;
704 if (strcasecmp(field, "Section") == 0) {
706 fprintf(fp, "Section: %s\n", pkg->section);
708 #if defined HAVE_SHA256
709 } else if (strcasecmp(field, "SHA256sum") == 0) {
710 if (pkg->sha256sum) {
711 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
714 } else if (strcasecmp(field, "Size") == 0) {
716 fprintf(fp, "Size: %s\n", pkg->size);
718 } else if (strcasecmp(field, "Source") == 0) {
720 fprintf(fp, "Source: %s\n", pkg->source);
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);
727 if (pflag == NULL || pstat == NULL || pwant == NULL)
730 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, 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]);
744 goto UNKNOWN_FMT_FIELD;
749 if (strcasecmp(field, "Tags") == 0) {
751 fprintf(fp, "Tags: %s\n", pkg->tags);
758 char *version = pkg_version_str_alloc(pkg);
761 fprintf(fp, "Version: %s\n", version);
766 goto UNKNOWN_FMT_FIELD;
772 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
775 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
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");
801 void pkg_print_status(pkg_t * pkg, FILE * file)
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.
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.
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.
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");
845 * libdpkg - Debian packaging suite library routines
846 * vercmp.c - comparison of version numbers
848 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
850 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
854 if (pkg->epoch > ref_pkg->epoch) {
858 if (pkg->epoch < ref_pkg->epoch) {
862 r = verrevcmp(pkg->version, ref_pkg->version);
867 r = verrevcmp(pkg->revision, ref_pkg->revision);
875 /* assume ascii; warning: evaluates x multiple times! */
876 #define order(x) ((x) == '~' ? -1 \
879 : isalpha((x)) ? (x) \
882 static int verrevcmp(const char *val, const char *ref) {
886 while (*val || *ref) {
889 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
890 int vc= order(*val), rc= order(*ref);
891 if (vc != rc) return vc - rc;
895 while ( *val == '0' ) val++;
896 while ( *ref == '0' ) ref++;
897 while (isdigit(*val) && isdigit(*ref)) {
898 if (!first_diff) first_diff= *val - *ref;
901 if (isdigit(*val)) return 1;
902 if (isdigit(*ref)) return -1;
903 if (first_diff) return first_diff;
908 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
912 r = pkg_compare_versions(it, ref);
914 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
918 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
922 if (strcmp(op, "<<") == 0) {
926 if (strcmp(op, ">>") == 0) {
930 if (strcmp(op, "=") == 0) {
934 fprintf(stderr, "unknown operator: %s", op);
938 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
940 const pkg_t *a = *(const pkg_t**) p1;
941 const pkg_t *b = *(const pkg_t**) p2;
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);
950 namecmp = strcmp(a->name, b->name);
953 vercmp = pkg_compare_versions(a, b);
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);
961 if (a->arch_priority > b->arch_priority)
963 if (a->arch_priority < b->arch_priority)
968 int abstract_pkg_name_compare(const void *p1, const void *p2)
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);
977 return strcmp(a->name, b->name);
982 pkg_version_str_alloc(pkg_t *pkg)
988 sprintf_alloc(&version, "%d:%s-%s",
989 pkg->epoch, pkg->version, pkg->revision);
991 sprintf_alloc(&version, "%d:%s",
992 pkg->epoch, pkg->version);
995 sprintf_alloc(&version, "%s-%s",
996 pkg->version, pkg->revision);
998 version = xstrdup(pkg->version);
1005 * XXX: this should be broken into two functions
1007 str_list_t *pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
1010 char *list_file_name = NULL;
1011 FILE *list_file = NULL;
1013 char *installed_file_name;
1016 pkg->installed_files_ref_cnt++;
1018 if (pkg->installed_files) {
1019 return pkg->installed_files;
1022 pkg->installed_files = str_list_alloc();
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.
1027 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1028 if (pkg->local_filename == NULL) {
1029 return pkg->installed_files;
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);
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;
1044 list_file = fdopen(fd, "rw+");
1045 if (list_file == NULL) {
1046 opkg_message(conf, OPKG_ERROR, "%s: fdopen: %s",
1047 __FUNCTION__, strerror(errno));
1049 unlink(list_file_name);
1050 free(list_file_name);
1051 return pkg->installed_files;
1053 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1055 opkg_message(conf, OPKG_ERROR, "%s: Error extracting file list "
1056 "from %s: %s\n", __FUNCTION__,
1057 pkg->local_filename, strerror(err));
1059 unlink(list_file_name);
1060 free(list_file_name);
1061 return pkg->installed_files;
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;
1074 free(list_file_name);
1077 if (conf->offline_root)
1078 rootdirlen = strlen(conf->offline_root);
1083 line = file_read_line_alloc(list_file);
1090 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1091 if (*file_name == '.') {
1094 if (*file_name == '/') {
1097 sprintf_alloc(&installed_file_name, "%s%s",
1098 pkg->dest->root_dir, file_name);
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);
1105 // already contains root_dir as header -> ABSOLUTE
1106 sprintf_alloc(&installed_file_name, "%s", file_name);
1109 str_list_append(pkg->installed_files, installed_file_name);
1110 free(installed_file_name);
1116 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1117 unlink(list_file_name);
1118 free(list_file_name);
1121 return pkg->installed_files;
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
1129 int pkg_free_installed_files(pkg_t *pkg)
1131 pkg->installed_files_ref_cnt--;
1133 if (pkg->installed_files_ref_cnt > 0)
1136 if (pkg->installed_files) {
1137 str_list_purge(pkg->installed_files);
1140 pkg->installed_files = NULL;
1145 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1148 char *list_file_name;
1150 //I don't think pkg_free_installed_files should be called here. Jamey
1151 //pkg_free_installed_files(pkg);
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);
1166 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1168 conffile_list_elt_t *iter;
1169 conffile_t *conffile;
1175 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1176 conffile = (conffile_t *)iter->data;
1178 if (strcmp(conffile->name, file_name) == 0) {
1186 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1187 const char *script, const char *args)
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. */
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)
1208 if (conf->offline_root) {
1209 if (conf->offline_root_path) {
1210 setenv("PATH", conf->offline_root_path, 1);
1212 opkg_message(conf, OPKG_NOTICE,
1213 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1216 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1217 setenv("D", conf->offline_root, 1);
1220 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1221 maintainer script within a chroot environment. */
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);
1231 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
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);
1238 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1241 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1244 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1246 if (! file_exists(path)) {
1251 sprintf_alloc(&cmd, "%s %s", path, args);
1254 const char *argv[] = {"sh", "-c", cmd, NULL};
1255 err = xsystem(argv);
1260 fprintf(stderr, "%s script returned status %d\n", script, err);
1267 char *pkg_state_want_to_str(pkg_state_want_t sw)
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);
1277 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1279 return xstrdup("<STATE_WANT_UNKNOWN>");
1282 pkg_state_want_t pkg_state_want_from_str(char *str)
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;
1292 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1297 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1300 int len = 3; /* ok\000 is minimum */
1303 /* clear the temporary flags before converting to string */
1304 sf &= SF_NONVOLATILE_FLAGS;
1307 return xstrdup("ok");
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;
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);
1324 str[len-1] = 0; /* squash last comma */
1329 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1334 if (strcmp(str, "ok") == 0) {
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;
1343 if (str[0] == ',') {
1354 char *pkg_state_status_to_str(pkg_state_status_t ss)
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);
1364 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1366 return xstrdup("<STATE_STATUS_UNKNOWN>");
1369 pkg_state_status_t pkg_state_status_from_str(const char *str)
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;
1379 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1381 return SS_NOT_INSTALLED;
1384 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1386 nv_pair_list_elt_t *l;
1388 if (!pkg->architecture)
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);
1399 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1403 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1405 nv_pair_list_elt_t *l;
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);
1417 int pkg_info_preinstall_check(opkg_conf_t *conf)
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();
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;
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);
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;
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;
1451 pkg_vec_free(available_pkgs);
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);
1464 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, 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);
1471 pkg_free_installed_files(pkg);
1473 pkg_vec_free(installed_pkgs);
1478 struct pkg_write_filelist_data {
1484 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
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);
1493 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1495 struct pkg_write_filelist_data data;
1496 char *list_file_name = NULL;
1500 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
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");
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");
1514 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1515 list_file_name, strerror(errno));
1520 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1521 fclose(data.stream);
1522 free(list_file_name);
1524 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1529 int pkg_write_changed_filelists(opkg_conf_t *conf)
1531 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1532 hash_table_t *pkg_hash = &conf->pkg_hash;
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);
1546 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1549 pkg_vec_free (installed_pkgs);