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" }
84 pkg->architecture = NULL;
85 pkg->maintainer = NULL;
87 pkg->description = NULL;
88 pkg->state_want = SW_UNKNOWN;
89 pkg->state_flag = SF_OK;
90 pkg->state_status = SS_NOT_INSTALLED;
91 pkg->depends_str = NULL;
92 pkg->provides_str = NULL;
93 pkg->depends_count = 0;
95 pkg->suggests_str = NULL;
96 pkg->recommends_str = NULL;
97 pkg->suggests_count = 0;
98 pkg->recommends_count = 0;
100 active_list_init(&pkg->list);
102 /* Abhaya: added init for conflicts fields */
103 pkg->conflicts = NULL;
104 pkg->conflicts_count = 0;
106 /* added for replaces. Jamey 7/23/2002 */
107 pkg->replaces = NULL;
108 pkg->replaces_count = 0;
110 pkg->pre_depends_count = 0;
111 pkg->pre_depends_str = NULL;
112 pkg->provides_count = 0;
113 pkg->provides = NULL;
114 pkg->filename = NULL;
115 pkg->local_filename = NULL;
116 pkg->tmp_unpack_dir = NULL;
118 #if defined HAVE_SHA256
119 pkg->sha256sum = NULL;
122 pkg->installed_size = NULL;
123 pkg->priority = NULL;
125 conffile_list_init(&pkg->conffiles);
126 pkg->installed_files = NULL;
127 pkg->installed_files_ref_cnt = 0;
129 pkg->provided_by_hand = 0;
137 pkg = xcalloc(1, sizeof(pkg_t));
144 compound_depend_deinit(compound_depend_t *depends)
147 for (i = 0; i < depends->possibility_count; i++)
150 d = depends->possibilities[i];
154 free (depends->possibilities);
158 pkg_deinit(pkg_t *pkg)
171 /* revision shares storage with version, so don't free */
172 pkg->revision = NULL;
174 /* owned by opkg_conf_t */
176 /* owned by opkg_conf_t */
179 if (pkg->architecture)
180 free(pkg->architecture);
181 pkg->architecture = NULL;
184 free(pkg->maintainer);
185 pkg->maintainer = NULL;
191 if (pkg->description)
192 free(pkg->description);
193 pkg->description = NULL;
195 pkg->state_want = SW_UNKNOWN;
196 pkg->state_flag = SF_OK;
197 pkg->state_status = SS_NOT_INSTALLED;
199 active_list_clear(&pkg->list);
202 free (pkg->replaces);
203 pkg->replaces = NULL;
206 int count = pkg->pre_depends_count
208 + pkg->recommends_count
209 + pkg->suggests_count;
211 for (i=0; i<count; i++)
212 compound_depend_deinit (&pkg->depends[i]);
216 if (pkg->conflicts) {
217 for (i=0; i<pkg->conflicts_count; i++)
218 compound_depend_deinit (&pkg->conflicts[i]);
219 free (pkg->conflicts);
223 free (pkg->provides);
225 pkg->pre_depends_count = 0;
226 pkg->provides_count = 0;
230 pkg->filename = NULL;
232 if (pkg->local_filename)
233 free(pkg->local_filename);
234 pkg->local_filename = NULL;
236 /* CLEANUP: It'd be nice to pullin the cleanup function from
237 opkg_install.c here. See comment in
238 opkg_install.c:cleanup_temporary_files */
239 if (pkg->tmp_unpack_dir)
240 free(pkg->tmp_unpack_dir);
241 pkg->tmp_unpack_dir = NULL;
247 #if defined HAVE_SHA256
249 free(pkg->sha256sum);
250 pkg->sha256sum = NULL;
257 if (pkg->installed_size)
258 free(pkg->installed_size);
259 pkg->installed_size = NULL;
263 pkg->priority = NULL;
269 conffile_list_deinit(&pkg->conffiles);
271 /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
272 since if they are calling deinit, they should know. Maybe do an
273 assertion here instead? */
274 pkg->installed_files_ref_cnt = 1;
275 pkg_free_installed_files(pkg);
284 pkg_init_from_file(opkg_conf_t *conf, pkg_t *pkg, const char *filename)
292 pkg->local_filename = xstrdup(filename);
294 sprintf_alloc(&control_path, "%s/%s.control.XXXXXX",
297 fd = mkstemp(control_path);
299 perror_msg("%s: mkstemp(%s)", __FUNCTION__, control_path);
304 control_file = fdopen(fd, "r+");
305 if (control_file == NULL) {
306 perror_msg("%s: fdopen", __FUNCTION__, control_path);
312 err = pkg_extract_control_file_to_stream(pkg, control_file);
316 rewind(control_file);
318 if (pkg_parse_from_stream(pkg, control_file, PFM_ALL))
322 fclose(control_file);
324 unlink(control_path);
331 /* Merge any new information in newpkg into oldpkg */
332 /* XXX: CLEANUP: This function shouldn't actually modify anything in
333 newpkg, but should leave it usable. This rework is so that
334 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
336 * uh, i thought that i had originally written this so that it took
337 * two pkgs and returned a new one? we can do that again... -sma
340 pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
342 if (oldpkg == newpkg) {
346 if (!oldpkg->auto_installed)
347 oldpkg->auto_installed = newpkg->auto_installed;
350 oldpkg->src = newpkg->src;
352 oldpkg->dest = newpkg->dest;
353 if (!oldpkg->architecture)
354 oldpkg->architecture = xstrdup(newpkg->architecture);
355 if (!oldpkg->arch_priority)
356 oldpkg->arch_priority = newpkg->arch_priority;
357 if (!oldpkg->section)
358 oldpkg->section = xstrdup(newpkg->section);
359 if(!oldpkg->maintainer)
360 oldpkg->maintainer = xstrdup(newpkg->maintainer);
361 if(!oldpkg->description)
362 oldpkg->description = xstrdup(newpkg->description);
364 /* merge the state_flags from the new package */
365 oldpkg->state_want = newpkg->state_want;
366 oldpkg->state_status = newpkg->state_status;
367 oldpkg->state_flag = newpkg->state_flag;
369 if (oldpkg->state_want == SW_UNKNOWN)
370 oldpkg->state_want = newpkg->state_want;
371 if (oldpkg->state_status == SS_NOT_INSTALLED)
372 oldpkg->state_status = newpkg->state_status;
373 oldpkg->state_flag |= newpkg->state_flag;
376 if (!oldpkg->depends_count && !oldpkg->pre_depends_count && !oldpkg->recommends_count && !oldpkg->suggests_count) {
377 oldpkg->depends_count = newpkg->depends_count;
378 newpkg->depends_count = 0;
380 oldpkg->depends = newpkg->depends;
381 newpkg->depends = NULL;
383 oldpkg->pre_depends_count = newpkg->pre_depends_count;
384 newpkg->pre_depends_count = 0;
386 oldpkg->recommends_count = newpkg->recommends_count;
387 newpkg->recommends_count = 0;
389 oldpkg->suggests_count = newpkg->suggests_count;
390 newpkg->suggests_count = 0;
393 if (oldpkg->provides_count <= 1) {
394 oldpkg->provides_count = newpkg->provides_count;
395 newpkg->provides_count = 0;
397 if (!oldpkg->provides) {
398 oldpkg->provides = newpkg->provides;
399 newpkg->provides = NULL;
403 if (!oldpkg->conflicts_count) {
404 oldpkg->conflicts_count = newpkg->conflicts_count;
405 newpkg->conflicts_count = 0;
407 oldpkg->conflicts = newpkg->conflicts;
408 newpkg->conflicts = NULL;
411 if (!oldpkg->replaces_count) {
412 oldpkg->replaces_count = newpkg->replaces_count;
413 newpkg->replaces_count = 0;
415 oldpkg->replaces = newpkg->replaces;
416 newpkg->replaces = NULL;
419 if (!oldpkg->filename)
420 oldpkg->filename = xstrdup(newpkg->filename);
421 if (!oldpkg->local_filename)
422 oldpkg->local_filename = xstrdup(newpkg->local_filename);
423 if (!oldpkg->tmp_unpack_dir)
424 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
426 oldpkg->md5sum = xstrdup(newpkg->md5sum);
427 #if defined HAVE_SHA256
428 if (!oldpkg->sha256sum)
429 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
432 oldpkg->size = xstrdup(newpkg->size);
433 if (!oldpkg->installed_size)
434 oldpkg->installed_size = xstrdup(newpkg->installed_size);
435 if (!oldpkg->priority)
436 oldpkg->priority = xstrdup(newpkg->priority);
438 oldpkg->source = xstrdup(newpkg->source);
439 if (nv_pair_list_empty(&oldpkg->conffiles)){
440 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
441 conffile_list_init(&newpkg->conffiles);
443 if (!oldpkg->installed_files){
444 oldpkg->installed_files = newpkg->installed_files;
445 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
446 newpkg->installed_files = NULL;
448 if (!oldpkg->essential)
449 oldpkg->essential = newpkg->essential;
455 abstract_pkg_init(abstract_pkg_t *ab_pkg)
457 ab_pkg->provided_by = abstract_pkg_vec_alloc();
458 ab_pkg->dependencies_checked = 0;
459 ab_pkg->state_status = SS_NOT_INSTALLED;
463 abstract_pkg_new(void)
465 abstract_pkg_t * ab_pkg;
467 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
468 abstract_pkg_init(ab_pkg);
474 set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
478 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
480 fp = fopen(file_name, "r");
482 opkg_message(conf, OPKG_ERROR, "fopen(%s): %s\n",
483 file_name, strerror(errno));
490 if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
491 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
500 pkg_state_want_to_str(pkg_state_want_t sw)
504 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
505 if (pkg_state_want_map[i].value == sw) {
506 return pkg_state_want_map[i].str;
510 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
512 return "<STATE_WANT_UNKNOWN>";
516 pkg_state_want_from_str(char *str)
520 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
521 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
522 return pkg_state_want_map[i].value;
526 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
532 pkg_state_flag_to_str(pkg_state_flag_t sf)
538 /* clear the temporary flags before converting to string */
539 sf &= SF_NONVOLATILE_FLAGS;
542 return xstrdup("ok");
545 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
546 if (sf & pkg_state_flag_map[i].value)
547 len += strlen(pkg_state_flag_map[i].str) + 1;
550 str = xmalloc(len+1);
553 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
554 if (sf & pkg_state_flag_map[i].value) {
555 strncat(str, pkg_state_flag_map[i].str, len);
556 strncat(str, ",", len);
561 str[len-1] = '\0'; /* squash last comma */
567 pkg_state_flag_from_str(const char *str)
572 if (strcmp(str, "ok") == 0) {
575 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
576 const char *sfname = pkg_state_flag_map[i].str;
577 int sfname_len = strlen(sfname);
578 if (strncmp(str, sfname, sfname_len) == 0) {
579 sf |= pkg_state_flag_map[i].value;
593 pkg_state_status_to_str(pkg_state_status_t ss)
597 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
598 if (pkg_state_status_map[i].value == ss) {
599 return pkg_state_status_map[i].str;
603 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
605 return "<STATE_STATUS_UNKNOWN>";
609 pkg_state_status_from_str(const char *str)
613 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
614 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
615 return pkg_state_status_map[i].value;
619 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
621 return SS_NOT_INSTALLED;
625 pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
629 int depends_count = pkg->pre_depends_count +
631 pkg->recommends_count +
634 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
635 goto UNKNOWN_FMT_FIELD;
642 if (strcasecmp(field, "Architecture") == 0) {
643 if (pkg->architecture) {
644 fprintf(fp, "Architecture: %s\n", pkg->architecture);
646 } else if (strcasecmp(field, "Auto-Installed") == 0) {
647 if (pkg->auto_installed)
648 fprintf(fp, "Auto-Installed: yes\n");
650 goto UNKNOWN_FMT_FIELD;
655 if (strcasecmp(field, "Conffiles") == 0) {
656 conffile_list_elt_t *iter;
658 if (nv_pair_list_empty(&pkg->conffiles))
661 fprintf(fp, "Conffiles:\n");
662 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
663 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
664 fprintf(fp, " %s %s\n",
665 ((conffile_t *)iter->data)->name,
666 ((conffile_t *)iter->data)->value);
669 } else if (strcasecmp(field, "Conflicts") == 0) {
671 if (pkg->conflicts_count) {
672 fprintf(fp, "Conflicts:");
673 for(i = 0; i < pkg->conflicts_count; i++) {
674 cdep = pkg->conflicts[i].possibilities[0];
675 fprintf(fp, "%s %s", i == 0 ? "" : ",",
678 fprintf(fp, " (%s%s)",
679 constraint_to_str(cdep->constraint),
686 goto UNKNOWN_FMT_FIELD;
691 if (strcasecmp(field, "Depends") == 0) {
692 if (pkg->depends_count) {
693 fprintf(fp, "Depends:");
694 for (j=0, i=0; i<depends_count; i++) {
695 if (pkg->depends[i].type != DEPEND)
697 str = pkg_depend_str(pkg, i);
698 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
704 } else if (strcasecmp(field, "Description") == 0) {
705 if (pkg->description) {
706 fprintf(fp, "Description: %s\n", pkg->description);
709 goto UNKNOWN_FMT_FIELD;
714 if (pkg->essential) {
715 fprintf(fp, "Essential: yes\n");
721 fprintf(fp, "Filename: %s\n", pkg->filename);
726 if (strcasecmp(field, "Installed-Size") == 0) {
727 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
728 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
729 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
734 if (strcasecmp(field, "Maintainer") == 0) {
735 if (pkg->maintainer) {
736 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
738 } else if (strcasecmp(field, "MD5sum") == 0) {
740 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
743 goto UNKNOWN_FMT_FIELD;
748 if (strcasecmp(field, "Package") == 0) {
749 fprintf(fp, "Package: %s\n", pkg->name);
750 } else if (strcasecmp(field, "Priority") == 0) {
751 fprintf(fp, "Priority: %s\n", pkg->priority);
752 } else if (strcasecmp(field, "Provides") == 0) {
753 if (pkg->provides_count) {
754 fprintf(fp, "Provides:");
755 for(i = 1; i < pkg->provides_count; i++) {
756 fprintf(fp, "%s %s", i == 1 ? "" : ",",
757 pkg->provides[i]->name);
762 goto UNKNOWN_FMT_FIELD;
767 if (strcasecmp (field, "Replaces") == 0) {
768 if (pkg->replaces_count) {
769 fprintf(fp, "Replaces:");
770 for (i = 0; i < pkg->replaces_count; i++) {
771 fprintf(fp, "%s %s", i == 0 ? "" : ",",
772 pkg->replaces[i]->name);
776 } else if (strcasecmp (field, "Recommends") == 0) {
777 if (pkg->recommends_count) {
778 fprintf(fp, "Recommends:");
779 for (j=0, i=0; i<depends_count; i++) {
780 if (pkg->depends[i].type != RECOMMEND)
782 str = pkg_depend_str(pkg, i);
783 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
790 goto UNKNOWN_FMT_FIELD;
795 if (strcasecmp(field, "Section") == 0) {
797 fprintf(fp, "Section: %s\n", pkg->section);
799 #if defined HAVE_SHA256
800 } else if (strcasecmp(field, "SHA256sum") == 0) {
801 if (pkg->sha256sum) {
802 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
805 } else if (strcasecmp(field, "Size") == 0) {
807 fprintf(fp, "Size: %s\n", pkg->size);
809 } else if (strcasecmp(field, "Source") == 0) {
811 fprintf(fp, "Source: %s\n", pkg->source);
813 } else if (strcasecmp(field, "Status") == 0) {
814 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
815 fprintf(fp, "Status: %s %s %s\n",
816 pkg_state_want_to_str(pkg->state_want),
818 pkg_state_status_to_str(pkg->state_status));
820 } else if (strcasecmp(field, "Suggests") == 0) {
821 if (pkg->suggests_count) {
822 fprintf(fp, "Suggests:");
823 for (j=0, i=0; i<depends_count; i++) {
824 if (pkg->depends[i].type != SUGGEST)
826 str = pkg_depend_str(pkg, i);
827 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
834 goto UNKNOWN_FMT_FIELD;
839 if (strcasecmp(field, "Tags") == 0) {
841 fprintf(fp, "Tags: %s\n", pkg->tags);
848 char *version = pkg_version_str_alloc(pkg);
851 fprintf(fp, "Version: %s\n", version);
856 goto UNKNOWN_FMT_FIELD;
862 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
866 pkg_formatted_info(FILE *fp, pkg_t *pkg)
868 pkg_formatted_field(fp, pkg, "Package");
869 pkg_formatted_field(fp, pkg, "Version");
870 pkg_formatted_field(fp, pkg, "Depends");
871 pkg_formatted_field(fp, pkg, "Recommends");
872 pkg_formatted_field(fp, pkg, "Suggests");
873 pkg_formatted_field(fp, pkg, "Provides");
874 pkg_formatted_field(fp, pkg, "Replaces");
875 pkg_formatted_field(fp, pkg, "Conflicts");
876 pkg_formatted_field(fp, pkg, "Status");
877 pkg_formatted_field(fp, pkg, "Section");
878 pkg_formatted_field(fp, pkg, "Essential");
879 pkg_formatted_field(fp, pkg, "Architecture");
880 pkg_formatted_field(fp, pkg, "Maintainer");
881 pkg_formatted_field(fp, pkg, "MD5sum");
882 pkg_formatted_field(fp, pkg, "Size");
883 pkg_formatted_field(fp, pkg, "Filename");
884 pkg_formatted_field(fp, pkg, "Conffiles");
885 pkg_formatted_field(fp, pkg, "Source");
886 pkg_formatted_field(fp, pkg, "Description");
887 pkg_formatted_field(fp, pkg, "Installed-Time");
888 pkg_formatted_field(fp, pkg, "Tags");
893 pkg_print_status(pkg_t * pkg, FILE * file)
899 /* XXX: QUESTION: Do we actually want more fields here? The
900 original idea was to save space by installing only what was
901 needed for actual computation, (package, version, status,
902 essential, conffiles). The assumption is that all other fields
903 can be found in th available file.
905 But, someone proposed the idea to make it possible to
906 reconstruct a .opk from an installed package, (ie. for beaming
907 from one handheld to another). So, maybe we actually want a few
908 more fields here, (depends, suggests, etc.), so that that would
909 be guaranteed to work even in the absence of more information
910 from the available file.
912 28-MAR-03: kergoth and I discussed this yesterday. We think
913 the essential info needs to be here for all installed packages
914 because they may not appear in the Packages files on various
915 feeds. Furthermore, one should be able to install from URL or
916 local storage without requiring a Packages file from any feed.
919 pkg_formatted_field(file, pkg, "Package");
920 pkg_formatted_field(file, pkg, "Version");
921 pkg_formatted_field(file, pkg, "Depends");
922 pkg_formatted_field(file, pkg, "Recommends");
923 pkg_formatted_field(file, pkg, "Suggests");
924 pkg_formatted_field(file, pkg, "Provides");
925 pkg_formatted_field(file, pkg, "Replaces");
926 pkg_formatted_field(file, pkg, "Conflicts");
927 pkg_formatted_field(file, pkg, "Status");
928 pkg_formatted_field(file, pkg, "Essential");
929 pkg_formatted_field(file, pkg, "Architecture");
930 pkg_formatted_field(file, pkg, "Conffiles");
931 pkg_formatted_field(file, pkg, "Installed-Time");
932 pkg_formatted_field(file, pkg, "Auto-Installed");
937 * libdpkg - Debian packaging suite library routines
938 * vercmp.c - comparison of version numbers
940 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
943 /* assume ascii; warning: evaluates x multiple times! */
944 #define order(x) ((x) == '~' ? -1 \
947 : isalpha((x)) ? (x) \
951 verrevcmp(const char *val, const char *ref) {
955 while (*val || *ref) {
958 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
959 int vc= order(*val), rc= order(*ref);
960 if (vc != rc) return vc - rc;
964 while ( *val == '0' ) val++;
965 while ( *ref == '0' ) ref++;
966 while (isdigit(*val) && isdigit(*ref)) {
967 if (!first_diff) first_diff= *val - *ref;
970 if (isdigit(*val)) return 1;
971 if (isdigit(*ref)) return -1;
972 if (first_diff) return first_diff;
978 pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
982 if (pkg->epoch > ref_pkg->epoch) {
986 if (pkg->epoch < ref_pkg->epoch) {
990 r = verrevcmp(pkg->version, ref_pkg->version);
995 r = verrevcmp(pkg->revision, ref_pkg->revision);
1005 pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
1009 r = pkg_compare_versions(it, ref);
1011 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
1015 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
1019 if (strcmp(op, "<<") == 0) {
1023 if (strcmp(op, ">>") == 0) {
1027 if (strcmp(op, "=") == 0) {
1031 fprintf(stderr, "unknown operator: %s", op);
1036 pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
1038 const pkg_t *a = *(const pkg_t**) p1;
1039 const pkg_t *b = *(const pkg_t**) p2;
1042 if (!a->name || !b->name) {
1043 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
1044 a, a->name, b, b->name);
1048 namecmp = strcmp(a->name, b->name);
1051 vercmp = pkg_compare_versions(a, b);
1054 if (!a->arch_priority || !b->arch_priority) {
1055 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
1056 a, a->arch_priority, b, b->arch_priority);
1059 if (a->arch_priority > b->arch_priority)
1061 if (a->arch_priority < b->arch_priority)
1067 abstract_pkg_name_compare(const void *p1, const void *p2)
1069 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1070 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1071 if (!a->name || !b->name) {
1072 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
1073 a, a->name, b, b->name);
1076 return strcmp(a->name, b->name);
1081 pkg_version_str_alloc(pkg_t *pkg)
1087 sprintf_alloc(&version, "%d:%s-%s",
1088 pkg->epoch, pkg->version, pkg->revision);
1090 sprintf_alloc(&version, "%d:%s",
1091 pkg->epoch, pkg->version);
1094 sprintf_alloc(&version, "%s-%s",
1095 pkg->version, pkg->revision);
1097 version = xstrdup(pkg->version);
1104 * XXX: this should be broken into two functions
1107 pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
1110 char *list_file_name = NULL;
1111 FILE *list_file = NULL;
1113 char *installed_file_name;
1116 pkg->installed_files_ref_cnt++;
1118 if (pkg->installed_files) {
1119 return pkg->installed_files;
1122 pkg->installed_files = str_list_alloc();
1124 /* For uninstalled packages, get the file list directly from the package.
1125 For installed packages, look at the package.list file in the database.
1127 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1128 if (pkg->local_filename == NULL) {
1129 return pkg->installed_files;
1131 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1132 file. In other words, change deb_extract so that it can
1133 simply return the file list as a char *[] rather than
1134 insisting on writing in to a FILE * as it does now. */
1135 sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
1136 conf->tmp_dir, pkg->name);
1137 fd = mkstemp(list_file_name);
1139 opkg_message(conf, OPKG_ERROR, "%s: mkstemp(%s): %s",
1140 __FUNCTION__, list_file_name, strerror(errno));
1141 free(list_file_name);
1142 return pkg->installed_files;
1144 list_file = fdopen(fd, "r+");
1145 if (list_file == NULL) {
1146 opkg_message(conf, OPKG_ERROR, "%s: fdopen: %s",
1147 __FUNCTION__, strerror(errno));
1149 unlink(list_file_name);
1150 free(list_file_name);
1151 return pkg->installed_files;
1153 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1155 opkg_message(conf, OPKG_ERROR, "%s: Error extracting file list "
1156 "from %s: %s\n", __FUNCTION__,
1157 pkg->local_filename, strerror(err));
1159 unlink(list_file_name);
1160 free(list_file_name);
1161 return pkg->installed_files;
1165 sprintf_alloc(&list_file_name, "%s/%s.list",
1166 pkg->dest->info_dir, pkg->name);
1167 list_file = fopen(list_file_name, "r");
1168 if (list_file == NULL) {
1169 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
1170 __FUNCTION__, list_file_name, strerror(errno));
1171 free(list_file_name);
1172 return pkg->installed_files;
1174 free(list_file_name);
1177 if (conf->offline_root)
1178 rootdirlen = strlen(conf->offline_root);
1183 line = file_read_line_alloc(list_file);
1189 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1190 if (*file_name == '.') {
1193 if (*file_name == '/') {
1196 sprintf_alloc(&installed_file_name, "%s%s",
1197 pkg->dest->root_dir, file_name);
1199 if (conf->offline_root &&
1200 strncmp(conf->offline_root, file_name, rootdirlen)) {
1201 sprintf_alloc(&installed_file_name, "%s%s",
1202 conf->offline_root, file_name);
1204 // already contains root_dir as header -> ABSOLUTE
1205 sprintf_alloc(&installed_file_name, "%s", file_name);
1208 str_list_append(pkg->installed_files, installed_file_name);
1209 free(installed_file_name);
1215 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1216 unlink(list_file_name);
1217 free(list_file_name);
1220 return pkg->installed_files;
1223 /* XXX: CLEANUP: This function and it's counterpart,
1224 (pkg_get_installed_files), do not match our init/deinit naming
1225 convention. Nor the alloc/free convention. But, then again, neither
1226 of these conventions currrently fit the way these two functions
1229 pkg_free_installed_files(pkg_t *pkg)
1231 pkg->installed_files_ref_cnt--;
1233 if (pkg->installed_files_ref_cnt > 0)
1236 if (pkg->installed_files) {
1237 str_list_purge(pkg->installed_files);
1240 pkg->installed_files = NULL;
1244 pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1246 char *list_file_name;
1248 sprintf_alloc(&list_file_name, "%s/%s.list",
1249 pkg->dest->info_dir, pkg->name);
1251 if (!conf->noaction)
1252 (void)unlink(list_file_name);
1254 free(list_file_name);
1258 pkg_get_conffile(pkg_t *pkg, const char *file_name)
1260 conffile_list_elt_t *iter;
1261 conffile_t *conffile;
1267 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1268 conffile = (conffile_t *)iter->data;
1270 if (strcmp(conffile->name, file_name) == 0) {
1279 pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1280 const char *script, const char *args)
1289 /* XXX: CLEANUP: There must be a better way to handle maintainer
1290 scripts when running with offline_root mode and/or a dest other
1291 than '/'. I've been playing around with some clever chroot
1292 tricks and I might come up with something workable. */
1294 * Attempt to provide a restricted environment for offline operation
1295 * Need the following set as a minimum:
1296 * OPKG_OFFLINE_ROOT = absolute path to root dir
1297 * D = absolute path to root dir (for OE generated postinst)
1298 * PATH = something safe (a restricted set of utilities)
1301 if (conf->offline_root) {
1302 if (conf->offline_root_path) {
1303 setenv("PATH", conf->offline_root_path, 1);
1305 opkg_message(conf, OPKG_NOTICE,
1306 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1309 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1310 setenv("D", conf->offline_root, 1);
1313 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1314 maintainer script within a chroot environment. */
1316 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1317 have scripts in pkg->tmp_unpack_dir. */
1318 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1319 if (pkg->dest == NULL) {
1320 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1321 __FUNCTION__, pkg->name);
1324 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1326 if (pkg->tmp_unpack_dir == NULL) {
1327 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1328 __FUNCTION__, pkg->name);
1331 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1334 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1337 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1339 if (! file_exists(path)) {
1344 sprintf_alloc(&cmd, "%s %s", path, args);
1347 const char *argv[] = {"sh", "-c", cmd, NULL};
1348 err = xsystem(argv);
1353 fprintf(stderr, "%s script returned status %d\n", script, err);
1361 pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1363 nv_pair_list_elt_t *l;
1365 if (!pkg->architecture)
1368 list_for_each_entry(l , &conf->arch_list.head, node) {
1369 nv_pair_t *nv = (nv_pair_t *)l->data;
1370 if (strcmp(nv->name, pkg->architecture) == 0) {
1371 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1376 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1381 pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1383 nv_pair_list_elt_t *l;
1385 list_for_each_entry(l , &conf->arch_list.head, node) {
1386 nv_pair_t *nv = (nv_pair_t *)l->data;
1387 if (strcmp(nv->name, archname) == 0) {
1388 int priority = strtol(nv->value, NULL, 0);
1396 pkg_info_preinstall_check(opkg_conf_t *conf)
1399 hash_table_t *pkg_hash = &conf->pkg_hash;
1400 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1401 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1403 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1404 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1405 /* update arch_priority for each package */
1406 for (i = 0; i < available_pkgs->len; i++) {
1407 pkg_t *pkg = available_pkgs->pkgs[i];
1408 int arch_priority = 1;
1411 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1412 if (pkg->architecture)
1413 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1415 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1416 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1417 pkg->arch_priority = arch_priority;
1420 for (i = 0; i < available_pkgs->len; i++) {
1421 pkg_t *pkg = available_pkgs->pkgs[i];
1422 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1423 /* clear flags and want for any uninstallable package */
1424 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1425 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1426 pkg->state_want = SW_UNKNOWN;
1427 pkg->state_flag = 0;
1430 pkg_vec_free(available_pkgs);
1432 /* update the file owner data structure */
1433 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1434 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1435 for (i = 0; i < installed_pkgs->len; i++) {
1436 pkg_t *pkg = installed_pkgs->pkgs[i];
1437 str_list_t *installed_files = pkg_get_installed_files(conf, pkg); /* this causes installed_files to be cached */
1438 str_list_elt_t *iter, *niter;
1439 if (installed_files == NULL) {
1440 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1443 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1445 iter = niter, niter = str_list_next(installed_files, iter)) {
1446 char *installed_file = (char *) iter->data;
1447 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1448 file_hash_set_file_owner(conf, installed_file, pkg);
1450 pkg_free_installed_files(pkg);
1452 pkg_vec_free(installed_pkgs);
1455 struct pkg_write_filelist_data {
1462 pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1464 struct pkg_write_filelist_data *data = data_;
1465 pkg_t *entry = entry_;
1466 if (entry == data->pkg) {
1467 fprintf(data->stream, "%s\n", key);
1472 pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1474 struct pkg_write_filelist_data data;
1475 char *list_file_name;
1477 sprintf_alloc(&list_file_name, "%s/%s.list",
1478 pkg->dest->info_dir, pkg->name);
1480 opkg_message(conf, OPKG_INFO, "%s: creating %s file for pkg %s\n",
1481 __FUNCTION__, list_file_name, pkg->name);
1483 data.stream = fopen(list_file_name, "w");
1485 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s, \"w\"): %s\n",
1486 __FUNCTION__, list_file_name, strerror(errno));
1487 free(list_file_name);
1493 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1494 fclose(data.stream);
1495 free(list_file_name);
1497 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1503 pkg_write_changed_filelists(opkg_conf_t *conf)
1505 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1506 hash_table_t *pkg_hash = &conf->pkg_hash;
1507 int i, err, ret = 0;
1512 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n",
1515 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1516 for (i = 0; i < installed_pkgs->len; i++) {
1517 pkg_t *pkg = installed_pkgs->pkgs[i];
1518 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1519 err = pkg_write_filelist(conf, pkg);
1525 pkg_vec_free (installed_pkgs);