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->provides_count-1; i++)
212 free (pkg->provides_str[i]);
213 free(pkg->provides_str);
214 pkg->provides_str = NULL;
216 for (i = 0; i < pkg->conflicts_count; i++)
217 free (pkg->conflicts_str[i]);
218 free(pkg->conflicts_str);
219 pkg->conflicts_str = NULL;
221 for (i = 0; i < pkg->replaces_count; i++)
222 free (pkg->replaces_str[i]);
223 free(pkg->replaces_str);
224 pkg->replaces_str = NULL;
226 for (i = 0; i < pkg->recommends_count; i++)
227 free (pkg->recommends_str[i]);
228 free(pkg->recommends_str);
229 pkg->recommends_str = NULL;
231 for (i = 0; i < pkg->suggests_count; i++)
232 free (pkg->suggests_str[i]);
233 free(pkg->suggests_str);
234 pkg->suggests_str = NULL;
237 int count = pkg->pre_depends_count
239 + pkg->recommends_count
240 + pkg->suggests_count;
242 for (i=0; i<count; i++)
243 compound_depend_deinit (&pkg->depends[i]);
247 if (pkg->conflicts) {
248 for (i=0; i<pkg->conflicts_count; i++)
249 compound_depend_deinit (&pkg->conflicts[i]);
250 free (pkg->conflicts);
254 free (pkg->provides);
256 pkg->pre_depends_count = 0;
257 if (pkg->pre_depends_str)
258 free(pkg->pre_depends_str);
259 pkg->pre_depends_str = NULL;
261 pkg->provides_count = 0;
265 pkg->filename = NULL;
267 if (pkg->local_filename)
268 free(pkg->local_filename);
269 pkg->local_filename = NULL;
271 /* CLEANUP: It'd be nice to pullin the cleanup function from
272 opkg_install.c here. See comment in
273 opkg_install.c:cleanup_temporary_files */
274 if (pkg->tmp_unpack_dir)
275 free(pkg->tmp_unpack_dir);
276 pkg->tmp_unpack_dir = NULL;
282 #if defined HAVE_SHA256
284 free(pkg->sha256sum);
285 pkg->sha256sum = NULL;
292 if (pkg->installed_size)
293 free(pkg->installed_size);
294 pkg->installed_size = NULL;
298 pkg->priority = NULL;
304 conffile_list_deinit(&pkg->conffiles);
306 /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
307 since if they are calling deinit, they should know. Maybe do an
308 assertion here instead? */
309 pkg->installed_files_ref_cnt = 1;
310 pkg_free_installed_files(pkg);
319 pkg_init_from_file(pkg_t *pkg, const char *filename)
327 pkg->local_filename = xstrdup(filename);
329 sprintf_alloc(&control_path, "%s.control.XXXXXX", filename);
330 fd = mkstemp(control_path);
332 perror_msg("%s: mkstemp(%s)", __FUNCTION__, control_path);
337 control_file = fdopen(fd, "rw");
338 if (control_file == NULL) {
339 perror_msg("%s: fdopen", __FUNCTION__, control_path);
345 err = pkg_extract_control_file_to_stream(pkg, control_file);
349 rewind(control_file);
350 pkg_parse_from_stream(pkg, control_file, PFM_ALL);
353 fclose(control_file);
355 unlink(control_path);
362 /* Merge any new information in newpkg into oldpkg */
363 /* XXX: CLEANUP: This function shouldn't actually modify anything in
364 newpkg, but should leave it usable. This rework is so that
365 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
367 * uh, i thought that i had originally written this so that it took
368 * two pkgs and returned a new one? we can do that again... -sma
370 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
372 if (oldpkg == newpkg) {
377 oldpkg->src = newpkg->src;
379 oldpkg->dest = newpkg->dest;
380 if (!oldpkg->architecture)
381 oldpkg->architecture = xstrdup(newpkg->architecture);
382 if (!oldpkg->arch_priority)
383 oldpkg->arch_priority = newpkg->arch_priority;
384 if (!oldpkg->section)
385 oldpkg->section = xstrdup(newpkg->section);
386 if(!oldpkg->maintainer)
387 oldpkg->maintainer = xstrdup(newpkg->maintainer);
388 if(!oldpkg->description)
389 oldpkg->description = xstrdup(newpkg->description);
391 /* merge the state_flags from the new package */
392 oldpkg->state_want = newpkg->state_want;
393 oldpkg->state_status = newpkg->state_status;
394 oldpkg->state_flag = newpkg->state_flag;
396 if (oldpkg->state_want == SW_UNKNOWN)
397 oldpkg->state_want = newpkg->state_want;
398 if (oldpkg->state_status == SS_NOT_INSTALLED)
399 oldpkg->state_status = newpkg->state_status;
400 oldpkg->state_flag |= newpkg->state_flag;
403 if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
404 oldpkg->depends_str = newpkg->depends_str;
405 newpkg->depends_str = NULL;
406 oldpkg->depends_count = newpkg->depends_count;
407 newpkg->depends_count = 0;
409 oldpkg->depends = newpkg->depends;
410 newpkg->depends = NULL;
412 oldpkg->pre_depends_str = newpkg->pre_depends_str;
413 newpkg->pre_depends_str = NULL;
414 oldpkg->pre_depends_count = newpkg->pre_depends_count;
415 newpkg->pre_depends_count = 0;
417 oldpkg->recommends_str = newpkg->recommends_str;
418 newpkg->recommends_str = NULL;
419 oldpkg->recommends_count = newpkg->recommends_count;
420 newpkg->recommends_count = 0;
422 oldpkg->suggests_str = newpkg->suggests_str;
423 newpkg->suggests_str = NULL;
424 oldpkg->suggests_count = newpkg->suggests_count;
425 newpkg->suggests_count = 0;
428 if (!oldpkg->provides_str) {
429 oldpkg->provides_str = newpkg->provides_str;
430 newpkg->provides_str = NULL;
431 oldpkg->provides_count = newpkg->provides_count;
432 newpkg->provides_count = 0;
434 if (!oldpkg->provides) {
435 oldpkg->provides = newpkg->provides;
436 newpkg->provides = NULL;
440 if (!oldpkg->conflicts_str) {
441 oldpkg->conflicts_str = newpkg->conflicts_str;
442 newpkg->conflicts_str = NULL;
443 oldpkg->conflicts_count = newpkg->conflicts_count;
444 newpkg->conflicts_count = 0;
446 oldpkg->conflicts = newpkg->conflicts;
447 newpkg->conflicts = NULL;
450 if (!oldpkg->replaces_str) {
451 oldpkg->replaces_str = newpkg->replaces_str;
452 newpkg->replaces_str = NULL;
453 oldpkg->replaces_count = newpkg->replaces_count;
454 newpkg->replaces_count = 0;
456 oldpkg->replaces = newpkg->replaces;
457 newpkg->replaces = NULL;
460 if (!oldpkg->filename)
461 oldpkg->filename = xstrdup(newpkg->filename);
462 if (!oldpkg->local_filename)
463 oldpkg->local_filename = xstrdup(newpkg->local_filename);
464 if (!oldpkg->tmp_unpack_dir)
465 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
467 oldpkg->md5sum = xstrdup(newpkg->md5sum);
468 #if defined HAVE_SHA256
469 if (!oldpkg->sha256sum)
470 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
473 oldpkg->size = xstrdup(newpkg->size);
474 if (!oldpkg->installed_size)
475 oldpkg->installed_size = xstrdup(newpkg->installed_size);
476 if (!oldpkg->priority)
477 oldpkg->priority = xstrdup(newpkg->priority);
479 oldpkg->source = xstrdup(newpkg->source);
480 if (nv_pair_list_empty(&oldpkg->conffiles)){
481 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
482 conffile_list_init(&newpkg->conffiles);
484 if (!oldpkg->installed_files){
485 oldpkg->installed_files = newpkg->installed_files;
486 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
487 newpkg->installed_files = NULL;
489 if (!oldpkg->essential)
490 oldpkg->essential = newpkg->essential;
495 abstract_pkg_t *abstract_pkg_new(void)
497 abstract_pkg_t * ab_pkg;
499 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
501 if (ab_pkg == NULL) {
502 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
506 if ( abstract_pkg_init(ab_pkg) < 0 )
512 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
514 ab_pkg->provided_by = abstract_pkg_vec_alloc();
515 if (ab_pkg->provided_by==NULL){
518 ab_pkg->dependencies_checked = 0;
519 ab_pkg->state_status = SS_NOT_INSTALLED;
524 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
528 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
530 fp = fopen(file_name, "r");
532 opkg_message(conf, OPKG_ERROR, "fopen(%s): %s\n",
533 file_name, strerror(errno));
540 if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
541 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
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) {
589 if (pkg->conflicts_count) {
590 fprintf(fp, "Conflicts:");
591 for(i = 0; i < pkg->conflicts_count; i++) {
592 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
597 goto UNKNOWN_FMT_FIELD;
602 if (strcasecmp(field, "Depends") == 0) {
603 if (pkg->depends_count) {
604 fprintf(fp, "Depends:");
605 for(i = 0; i < pkg->depends_count; i++) {
606 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
610 } else if (strcasecmp(field, "Description") == 0) {
611 if (pkg->description) {
612 fprintf(fp, "Description: %s\n", pkg->description);
615 goto UNKNOWN_FMT_FIELD;
620 if (pkg->essential) {
621 fprintf(fp, "Essential: yes\n");
627 fprintf(fp, "Filename: %s\n", pkg->filename);
632 if (strcasecmp(field, "Installed-Size") == 0) {
633 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
634 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
635 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
640 if (strcasecmp(field, "Maintainer") == 0) {
641 if (pkg->maintainer) {
642 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
644 } else if (strcasecmp(field, "MD5sum") == 0) {
646 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
649 goto UNKNOWN_FMT_FIELD;
654 if (strcasecmp(field, "Package") == 0) {
655 fprintf(fp, "Package: %s\n", pkg->name);
656 } else if (strcasecmp(field, "Priority") == 0) {
657 fprintf(fp, "Priority: %s\n", pkg->priority);
658 } else if (strcasecmp(field, "Provides") == 0) {
659 if (pkg->provides_count) {
660 fprintf(fp, "Provides:");
661 for(i = 0; i < pkg->provides_count-1; i++) {
662 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->provides_str[i]);
667 goto UNKNOWN_FMT_FIELD;
672 if (strcasecmp (field, "Replaces") == 0) {
673 if (pkg->replaces_count) {
674 fprintf(fp, "Replaces:");
675 for (i = 0; i < pkg->replaces_count; i++) {
676 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
680 } else if (strcasecmp (field, "Recommends") == 0) {
681 if (pkg->recommends_count) {
682 fprintf(fp, "Recommends:");
683 for(i = 0; i < pkg->recommends_count; i++) {
684 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
689 goto UNKNOWN_FMT_FIELD;
694 if (strcasecmp(field, "Section") == 0) {
696 fprintf(fp, "Section: %s\n", pkg->section);
698 #if defined HAVE_SHA256
699 } else if (strcasecmp(field, "SHA256sum") == 0) {
700 if (pkg->sha256sum) {
701 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
704 } else if (strcasecmp(field, "Size") == 0) {
706 fprintf(fp, "Size: %s\n", pkg->size);
708 } else if (strcasecmp(field, "Source") == 0) {
710 fprintf(fp, "Source: %s\n", pkg->source);
712 } else if (strcasecmp(field, "Status") == 0) {
713 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
714 char *pstat = pkg_state_status_to_str(pkg->state_status);
715 char *pwant = pkg_state_want_to_str(pkg->state_want);
717 if (pflag == NULL || pstat == NULL || pwant == NULL)
720 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
725 } else if (strcasecmp(field, "Suggests") == 0) {
726 if (pkg->suggests_count) {
727 fprintf(fp, "Suggests:");
728 for(i = 0; i < pkg->suggests_count; i++) {
729 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
734 goto UNKNOWN_FMT_FIELD;
739 if (strcasecmp(field, "Tags") == 0) {
741 fprintf(fp, "Tags: %s\n", pkg->tags);
748 char *version = pkg_version_str_alloc(pkg);
751 fprintf(fp, "Version: %s\n", version);
756 goto UNKNOWN_FMT_FIELD;
762 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
765 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
767 pkg_formatted_field(fp, pkg, "Package");
768 pkg_formatted_field(fp, pkg, "Version");
769 pkg_formatted_field(fp, pkg, "Depends");
770 pkg_formatted_field(fp, pkg, "Recommends");
771 pkg_formatted_field(fp, pkg, "Suggests");
772 pkg_formatted_field(fp, pkg, "Provides");
773 pkg_formatted_field(fp, pkg, "Replaces");
774 pkg_formatted_field(fp, pkg, "Conflicts");
775 pkg_formatted_field(fp, pkg, "Status");
776 pkg_formatted_field(fp, pkg, "Section");
777 pkg_formatted_field(fp, pkg, "Essential");
778 pkg_formatted_field(fp, pkg, "Architecture");
779 pkg_formatted_field(fp, pkg, "Maintainer");
780 pkg_formatted_field(fp, pkg, "MD5sum");
781 pkg_formatted_field(fp, pkg, "Size");
782 pkg_formatted_field(fp, pkg, "Filename");
783 pkg_formatted_field(fp, pkg, "Conffiles");
784 pkg_formatted_field(fp, pkg, "Source");
785 pkg_formatted_field(fp, pkg, "Description");
786 pkg_formatted_field(fp, pkg, "Installed-Time");
787 pkg_formatted_field(fp, pkg, "Tags");
791 void pkg_print_status(pkg_t * pkg, FILE * file)
797 /* XXX: QUESTION: Do we actually want more fields here? The
798 original idea was to save space by installing only what was
799 needed for actual computation, (package, version, status,
800 essential, conffiles). The assumption is that all other fields
801 can be found in th available file.
803 But, someone proposed the idea to make it possible to
804 reconstruct a .opk from an installed package, (ie. for beaming
805 from one handheld to another). So, maybe we actually want a few
806 more fields here, (depends, suggests, etc.), so that that would
807 be guaranteed to work even in the absence of more information
808 from the available file.
810 28-MAR-03: kergoth and I discussed this yesterday. We think
811 the essential info needs to be here for all installed packages
812 because they may not appear in the Packages files on various
813 feeds. Furthermore, one should be able to install from URL or
814 local storage without requiring a Packages file from any feed.
817 pkg_formatted_field(file, pkg, "Package");
818 pkg_formatted_field(file, pkg, "Version");
819 pkg_formatted_field(file, pkg, "Depends");
820 pkg_formatted_field(file, pkg, "Recommends");
821 pkg_formatted_field(file, pkg, "Suggests");
822 pkg_formatted_field(file, pkg, "Provides");
823 pkg_formatted_field(file, pkg, "Replaces");
824 pkg_formatted_field(file, pkg, "Conflicts");
825 pkg_formatted_field(file, pkg, "Status");
826 pkg_formatted_field(file, pkg, "Essential");
827 pkg_formatted_field(file, pkg, "Architecture");
828 pkg_formatted_field(file, pkg, "Conffiles");
829 pkg_formatted_field(file, pkg, "Installed-Time");
830 pkg_formatted_field(file, pkg, "Auto-Installed");
835 * libdpkg - Debian packaging suite library routines
836 * vercmp.c - comparison of version numbers
838 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
840 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
844 if (pkg->epoch > ref_pkg->epoch) {
848 if (pkg->epoch < ref_pkg->epoch) {
852 r = verrevcmp(pkg->version, ref_pkg->version);
857 r = verrevcmp(pkg->revision, ref_pkg->revision);
865 /* assume ascii; warning: evaluates x multiple times! */
866 #define order(x) ((x) == '~' ? -1 \
869 : isalpha((x)) ? (x) \
872 static int verrevcmp(const char *val, const char *ref) {
876 while (*val || *ref) {
879 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
880 int vc= order(*val), rc= order(*ref);
881 if (vc != rc) return vc - rc;
885 while ( *val == '0' ) val++;
886 while ( *ref == '0' ) ref++;
887 while (isdigit(*val) && isdigit(*ref)) {
888 if (!first_diff) first_diff= *val - *ref;
891 if (isdigit(*val)) return 1;
892 if (isdigit(*ref)) return -1;
893 if (first_diff) return first_diff;
898 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
902 r = pkg_compare_versions(it, ref);
904 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
908 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
912 if (strcmp(op, "<<") == 0) {
916 if (strcmp(op, ">>") == 0) {
920 if (strcmp(op, "=") == 0) {
924 fprintf(stderr, "unknown operator: %s", op);
928 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
930 const pkg_t *a = *(const pkg_t**) p1;
931 const pkg_t *b = *(const pkg_t**) p2;
934 if (!a->name || !b->name) {
935 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
936 a, a->name, b, b->name);
940 namecmp = strcmp(a->name, b->name);
943 vercmp = pkg_compare_versions(a, b);
946 if (!a->arch_priority || !b->arch_priority) {
947 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
948 a, a->arch_priority, b, b->arch_priority);
951 if (a->arch_priority > b->arch_priority)
953 if (a->arch_priority < b->arch_priority)
958 int abstract_pkg_name_compare(const void *p1, const void *p2)
960 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
961 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
962 if (!a->name || !b->name) {
963 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
964 a, a->name, b, b->name);
967 return strcmp(a->name, b->name);
972 pkg_version_str_alloc(pkg_t *pkg)
978 sprintf_alloc(&version, "%d:%s-%s",
979 pkg->epoch, pkg->version, pkg->revision);
981 sprintf_alloc(&version, "%d:%s",
982 pkg->epoch, pkg->version);
985 sprintf_alloc(&version, "%s-%s",
986 pkg->version, pkg->revision);
988 version = xstrdup(pkg->version);
994 str_list_t *pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
997 char *list_file_name = NULL;
998 FILE *list_file = NULL;
1000 char *installed_file_name;
1003 pkg->installed_files_ref_cnt++;
1005 if (pkg->installed_files) {
1006 return pkg->installed_files;
1009 pkg->installed_files = str_list_alloc();
1011 /* For uninstalled packages, get the file list directly from the package.
1012 For installed packages, look at the package.list file in the database.
1014 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1015 if (pkg->local_filename == NULL) {
1016 return pkg->installed_files;
1018 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1019 file. In other words, change deb_extract so that it can
1020 simply return the file list as a char *[] rather than
1021 insisting on writing in to a FILE * as it does now. */
1022 list_file = tmpfile();
1023 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1026 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1027 __FUNCTION__, pkg->local_filename, strerror(err));
1028 return pkg->installed_files;
1032 sprintf_alloc(&list_file_name, "%s/%s.list",
1033 pkg->dest->info_dir, pkg->name);
1034 if (! file_exists(list_file_name)) {
1035 free(list_file_name);
1036 return pkg->installed_files;
1039 list_file = fopen(list_file_name, "r");
1040 if (list_file == NULL) {
1041 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1042 list_file_name, strerror(errno));
1043 free(list_file_name);
1044 return pkg->installed_files;
1046 free(list_file_name);
1049 if (conf->offline_root)
1050 rootdirlen = strlen(conf->offline_root);
1055 line = file_read_line_alloc(list_file);
1062 if (pkg->state_status == SS_NOT_INSTALLED) {
1063 if (*file_name == '.') {
1066 if (*file_name == '/') {
1069 sprintf_alloc(&installed_file_name, "%s%s",
1070 pkg->dest->root_dir, file_name);
1072 if (conf->offline_root &&
1073 strncmp(conf->offline_root, file_name, rootdirlen)) {
1074 sprintf_alloc(&installed_file_name, "%s%s",
1075 conf->offline_root, file_name);
1077 // already contains root_dir as header -> ABSOLUTE
1078 sprintf_alloc(&installed_file_name, "%s", file_name);
1081 str_list_append(pkg->installed_files, installed_file_name);
1082 free(installed_file_name);
1088 return pkg->installed_files;
1091 /* XXX: CLEANUP: This function and it's counterpart,
1092 (pkg_get_installed_files), do not match our init/deinit naming
1093 convention. Nor the alloc/free convention. But, then again, neither
1094 of these conventions currrently fit the way these two functions
1096 int pkg_free_installed_files(pkg_t *pkg)
1098 pkg->installed_files_ref_cnt--;
1100 if (pkg->installed_files_ref_cnt > 0)
1103 if (pkg->installed_files) {
1104 str_list_purge(pkg->installed_files);
1107 pkg->installed_files = NULL;
1112 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1115 char *list_file_name;
1117 //I don't think pkg_free_installed_files should be called here. Jamey
1118 //pkg_free_installed_files(pkg);
1120 sprintf_alloc(&list_file_name, "%s/%s.list",
1121 pkg->dest->info_dir, pkg->name);
1122 if (!conf->noaction) {
1123 err = unlink(list_file_name);
1124 free(list_file_name);
1133 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1135 conffile_list_elt_t *iter;
1136 conffile_t *conffile;
1142 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1143 conffile = (conffile_t *)iter->data;
1145 if (strcmp(conffile->name, file_name) == 0) {
1153 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1154 const char *script, const char *args)
1163 /* XXX: CLEANUP: There must be a better way to handle maintainer
1164 scripts when running with offline_root mode and/or a dest other
1165 than '/'. I've been playing around with some clever chroot
1166 tricks and I might come up with something workable. */
1168 * Attempt to provide a restricted environment for offline operation
1169 * Need the following set as a minimum:
1170 * OPKG_OFFLINE_ROOT = absolute path to root dir
1171 * D = absolute path to root dir (for OE generated postinst)
1172 * PATH = something safe (a restricted set of utilities)
1175 if (conf->offline_root) {
1176 if (conf->offline_root_path) {
1177 setenv("PATH", conf->offline_root_path, 1);
1179 opkg_message(conf, OPKG_NOTICE,
1180 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1183 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1184 setenv("D", conf->offline_root, 1);
1187 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1188 maintainer script within a chroot environment. */
1190 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1191 have scripts in pkg->tmp_unpack_dir. */
1192 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1193 if (pkg->dest == NULL) {
1194 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1195 __FUNCTION__, pkg->name);
1198 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1200 if (pkg->tmp_unpack_dir == NULL) {
1201 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1202 __FUNCTION__, pkg->name);
1205 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1208 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1211 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1213 if (! file_exists(path)) {
1218 sprintf_alloc(&cmd, "%s %s", path, args);
1221 const char *argv[] = {"sh", "-c", cmd, NULL};
1222 err = xsystem(argv);
1227 fprintf(stderr, "%s script returned status %d\n", script, err);
1234 char *pkg_state_want_to_str(pkg_state_want_t sw)
1238 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1239 if (pkg_state_want_map[i].value == sw) {
1240 return xstrdup(pkg_state_want_map[i].str);
1244 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1246 return xstrdup("<STATE_WANT_UNKNOWN>");
1249 pkg_state_want_t pkg_state_want_from_str(char *str)
1253 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1254 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1255 return pkg_state_want_map[i].value;
1259 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1264 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1267 int len = 3; /* ok\000 is minimum */
1270 /* clear the temporary flags before converting to string */
1271 sf &= SF_NONVOLATILE_FLAGS;
1274 return xstrdup("ok");
1277 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1278 if (sf & pkg_state_flag_map[i].value) {
1279 len += strlen(pkg_state_flag_map[i].str) + 1;
1284 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1285 if (sf & pkg_state_flag_map[i].value) {
1286 strcat(str, pkg_state_flag_map[i].str);
1291 str[len-1] = 0; /* squash last comma */
1296 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1301 if (strcmp(str, "ok") == 0) {
1304 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1305 const char *sfname = pkg_state_flag_map[i].str;
1306 int sfname_len = strlen(sfname);
1307 if (strncmp(str, sfname, sfname_len) == 0) {
1308 sf |= pkg_state_flag_map[i].value;
1310 if (str[0] == ',') {
1321 char *pkg_state_status_to_str(pkg_state_status_t ss)
1325 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1326 if (pkg_state_status_map[i].value == ss) {
1327 return xstrdup(pkg_state_status_map[i].str);
1331 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1333 return xstrdup("<STATE_STATUS_UNKNOWN>");
1336 pkg_state_status_t pkg_state_status_from_str(const char *str)
1340 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1341 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1342 return pkg_state_status_map[i].value;
1346 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1348 return SS_NOT_INSTALLED;
1351 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1353 nv_pair_list_elt_t *l;
1355 if (!pkg->architecture)
1358 list_for_each_entry(l , &conf->arch_list.head, node) {
1359 nv_pair_t *nv = (nv_pair_t *)l->data;
1360 if (strcmp(nv->name, pkg->architecture) == 0) {
1361 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1366 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1370 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1372 nv_pair_list_elt_t *l;
1374 list_for_each_entry(l , &conf->arch_list.head, node) {
1375 nv_pair_t *nv = (nv_pair_t *)l->data;
1376 if (strcmp(nv->name, archname) == 0) {
1377 int priority = strtol(nv->value, NULL, 0);
1384 int pkg_info_preinstall_check(opkg_conf_t *conf)
1387 hash_table_t *pkg_hash = &conf->pkg_hash;
1388 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1389 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1391 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1392 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1393 /* update arch_priority for each package */
1394 for (i = 0; i < available_pkgs->len; i++) {
1395 pkg_t *pkg = available_pkgs->pkgs[i];
1396 int arch_priority = 1;
1399 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1400 if (pkg->architecture)
1401 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1403 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1404 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1405 pkg->arch_priority = arch_priority;
1408 for (i = 0; i < available_pkgs->len; i++) {
1409 pkg_t *pkg = available_pkgs->pkgs[i];
1410 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1411 /* clear flags and want for any uninstallable package */
1412 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1413 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1414 pkg->state_want = SW_UNKNOWN;
1415 pkg->state_flag = 0;
1418 pkg_vec_free(available_pkgs);
1420 /* update the file owner data structure */
1421 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1422 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1423 for (i = 0; i < installed_pkgs->len; i++) {
1424 pkg_t *pkg = installed_pkgs->pkgs[i];
1425 str_list_t *installed_files = pkg_get_installed_files(conf, pkg); /* this causes installed_files to be cached */
1426 str_list_elt_t *iter, *niter;
1427 if (installed_files == NULL) {
1428 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1431 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1433 iter = niter, niter = str_list_next(installed_files, iter)) {
1434 char *installed_file = (char *) iter->data;
1435 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1436 file_hash_set_file_owner(conf, installed_file, pkg);
1438 pkg_free_installed_files(pkg);
1440 pkg_vec_free(installed_pkgs);
1445 struct pkg_write_filelist_data {
1451 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1453 struct pkg_write_filelist_data *data = data_;
1454 pkg_t *entry = entry_;
1455 if (entry == data->pkg) {
1456 fprintf(data->stream, "%s\n", key);
1460 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1462 struct pkg_write_filelist_data data;
1463 char *list_file_name = NULL;
1467 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1470 opkg_message(conf, OPKG_INFO,
1471 " creating %s.list file\n", pkg->name);
1472 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1473 if (!list_file_name) {
1474 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1477 opkg_message(conf, OPKG_INFO,
1478 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1479 data.stream = fopen(list_file_name, "w");
1481 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1482 list_file_name, strerror(errno));
1487 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1488 fclose(data.stream);
1489 free(list_file_name);
1491 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1496 int pkg_write_changed_filelists(opkg_conf_t *conf)
1498 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1499 hash_table_t *pkg_hash = &conf->pkg_hash;
1505 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1506 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1507 for (i = 0; i < installed_pkgs->len; i++) {
1508 pkg_t *pkg = installed_pkgs->pkgs[i];
1509 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1510 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1511 err = pkg_write_filelist(conf, pkg);
1513 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1516 pkg_vec_free (installed_pkgs);