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"
36 #include "opkg_conf.h"
38 typedef struct enum_map enum_map_t;
45 static const enum_map_t pkg_state_want_map[] = {
46 { SW_UNKNOWN, "unknown"},
47 { SW_INSTALL, "install"},
48 { SW_DEINSTALL, "deinstall"},
52 static const enum_map_t pkg_state_flag_map[] = {
54 { SF_REINSTREQ, "reinstreq"},
56 { SF_REPLACE, "replace"},
57 { SF_NOPRUNE, "noprune"},
58 { SF_PREFER, "prefer"},
59 { SF_OBSOLETE, "obsolete"},
63 static const enum_map_t pkg_state_status_map[] = {
64 { SS_NOT_INSTALLED, "not-installed" },
65 { SS_UNPACKED, "unpacked" },
66 { SS_HALF_CONFIGURED, "half-configured" },
67 { SS_INSTALLED, "installed" },
68 { SS_HALF_INSTALLED, "half-installed" },
69 { SS_CONFIG_FILES, "config-files" },
70 { SS_POST_INST_FAILED, "post-inst-failed" },
71 { SS_REMOVAL_FAILED, "removal-failed" }
83 pkg->architecture = NULL;
84 pkg->maintainer = NULL;
86 pkg->description = NULL;
87 pkg->state_want = SW_UNKNOWN;
88 pkg->state_flag = SF_OK;
89 pkg->state_status = SS_NOT_INSTALLED;
90 pkg->depends_str = NULL;
91 pkg->provides_str = NULL;
92 pkg->depends_count = 0;
94 pkg->suggests_str = NULL;
95 pkg->recommends_str = NULL;
96 pkg->suggests_count = 0;
97 pkg->recommends_count = 0;
99 active_list_init(&pkg->list);
101 /* Abhaya: added init for conflicts fields */
102 pkg->conflicts = NULL;
103 pkg->conflicts_count = 0;
105 /* added for replaces. Jamey 7/23/2002 */
106 pkg->replaces = NULL;
107 pkg->replaces_count = 0;
109 pkg->pre_depends_count = 0;
110 pkg->pre_depends_str = NULL;
111 pkg->provides_count = 0;
112 pkg->provides = NULL;
113 pkg->filename = NULL;
114 pkg->local_filename = NULL;
115 pkg->tmp_unpack_dir = NULL;
117 #if defined HAVE_SHA256
118 pkg->sha256sum = NULL;
121 pkg->installed_size = NULL;
122 pkg->priority = NULL;
124 conffile_list_init(&pkg->conffiles);
125 pkg->installed_files = NULL;
126 pkg->installed_files_ref_cnt = 0;
128 pkg->provided_by_hand = 0;
136 pkg = xcalloc(1, sizeof(pkg_t));
143 compound_depend_deinit(compound_depend_t *depends)
146 for (i = 0; i < depends->possibility_count; i++)
149 d = depends->possibilities[i];
153 free (depends->possibilities);
157 pkg_deinit(pkg_t *pkg)
170 /* revision shares storage with version, so don't free */
171 pkg->revision = NULL;
173 /* owned by opkg_conf_t */
175 /* owned by opkg_conf_t */
178 if (pkg->architecture)
179 free(pkg->architecture);
180 pkg->architecture = NULL;
183 free(pkg->maintainer);
184 pkg->maintainer = NULL;
190 if (pkg->description)
191 free(pkg->description);
192 pkg->description = NULL;
194 pkg->state_want = SW_UNKNOWN;
195 pkg->state_flag = SF_OK;
196 pkg->state_status = SS_NOT_INSTALLED;
198 active_list_clear(&pkg->list);
201 free (pkg->replaces);
202 pkg->replaces = NULL;
205 int count = pkg->pre_depends_count
207 + pkg->recommends_count
208 + pkg->suggests_count;
210 for (i=0; i<count; i++)
211 compound_depend_deinit (&pkg->depends[i]);
215 if (pkg->conflicts) {
216 for (i=0; i<pkg->conflicts_count; i++)
217 compound_depend_deinit (&pkg->conflicts[i]);
218 free (pkg->conflicts);
222 free (pkg->provides);
224 pkg->pre_depends_count = 0;
225 pkg->provides_count = 0;
229 pkg->filename = NULL;
231 if (pkg->local_filename)
232 free(pkg->local_filename);
233 pkg->local_filename = NULL;
235 /* CLEANUP: It'd be nice to pullin the cleanup function from
236 opkg_install.c here. See comment in
237 opkg_install.c:cleanup_temporary_files */
238 if (pkg->tmp_unpack_dir)
239 free(pkg->tmp_unpack_dir);
240 pkg->tmp_unpack_dir = NULL;
246 #if defined HAVE_SHA256
248 free(pkg->sha256sum);
249 pkg->sha256sum = NULL;
256 if (pkg->installed_size)
257 free(pkg->installed_size);
258 pkg->installed_size = NULL;
262 pkg->priority = NULL;
268 conffile_list_deinit(&pkg->conffiles);
270 /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
271 since if they are calling deinit, they should know. Maybe do an
272 assertion here instead? */
273 pkg->installed_files_ref_cnt = 1;
274 pkg_free_installed_files(pkg);
283 pkg_init_from_file(opkg_conf_t *conf, pkg_t *pkg, const char *filename)
291 pkg->local_filename = xstrdup(filename);
293 sprintf_alloc(&control_path, "%s/%s.control.XXXXXX",
296 fd = mkstemp(control_path);
298 perror_msg("%s: mkstemp(%s)", __FUNCTION__, control_path);
303 control_file = fdopen(fd, "r+");
304 if (control_file == NULL) {
305 perror_msg("%s: fdopen", __FUNCTION__, control_path);
311 err = pkg_extract_control_file_to_stream(pkg, control_file);
315 rewind(control_file);
317 if (pkg_parse_from_stream(pkg, control_file, PFM_ALL))
321 fclose(control_file);
323 unlink(control_path);
330 /* Merge any new information in newpkg into oldpkg */
331 /* XXX: CLEANUP: This function shouldn't actually modify anything in
332 newpkg, but should leave it usable. This rework is so that
333 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
335 * uh, i thought that i had originally written this so that it took
336 * two pkgs and returned a new one? we can do that again... -sma
339 pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
341 if (oldpkg == newpkg) {
345 if (!oldpkg->auto_installed)
346 oldpkg->auto_installed = newpkg->auto_installed;
349 oldpkg->src = newpkg->src;
351 oldpkg->dest = newpkg->dest;
352 if (!oldpkg->architecture)
353 oldpkg->architecture = xstrdup(newpkg->architecture);
354 if (!oldpkg->arch_priority)
355 oldpkg->arch_priority = newpkg->arch_priority;
356 if (!oldpkg->section)
357 oldpkg->section = xstrdup(newpkg->section);
358 if(!oldpkg->maintainer)
359 oldpkg->maintainer = xstrdup(newpkg->maintainer);
360 if(!oldpkg->description)
361 oldpkg->description = xstrdup(newpkg->description);
363 /* merge the state_flags from the new package */
364 oldpkg->state_want = newpkg->state_want;
365 oldpkg->state_status = newpkg->state_status;
366 oldpkg->state_flag = newpkg->state_flag;
368 if (oldpkg->state_want == SW_UNKNOWN)
369 oldpkg->state_want = newpkg->state_want;
370 if (oldpkg->state_status == SS_NOT_INSTALLED)
371 oldpkg->state_status = newpkg->state_status;
372 oldpkg->state_flag |= newpkg->state_flag;
375 if (!oldpkg->depends_count && !oldpkg->pre_depends_count && !oldpkg->recommends_count && !oldpkg->suggests_count) {
376 oldpkg->depends_count = newpkg->depends_count;
377 newpkg->depends_count = 0;
379 oldpkg->depends = newpkg->depends;
380 newpkg->depends = NULL;
382 oldpkg->pre_depends_count = newpkg->pre_depends_count;
383 newpkg->pre_depends_count = 0;
385 oldpkg->recommends_count = newpkg->recommends_count;
386 newpkg->recommends_count = 0;
388 oldpkg->suggests_count = newpkg->suggests_count;
389 newpkg->suggests_count = 0;
392 if (oldpkg->provides_count <= 1) {
393 oldpkg->provides_count = newpkg->provides_count;
394 newpkg->provides_count = 0;
396 if (!oldpkg->provides) {
397 oldpkg->provides = newpkg->provides;
398 newpkg->provides = NULL;
402 if (!oldpkg->conflicts_count) {
403 oldpkg->conflicts_count = newpkg->conflicts_count;
404 newpkg->conflicts_count = 0;
406 oldpkg->conflicts = newpkg->conflicts;
407 newpkg->conflicts = NULL;
410 if (!oldpkg->replaces_count) {
411 oldpkg->replaces_count = newpkg->replaces_count;
412 newpkg->replaces_count = 0;
414 oldpkg->replaces = newpkg->replaces;
415 newpkg->replaces = NULL;
418 if (!oldpkg->filename)
419 oldpkg->filename = xstrdup(newpkg->filename);
420 if (!oldpkg->local_filename)
421 oldpkg->local_filename = xstrdup(newpkg->local_filename);
422 if (!oldpkg->tmp_unpack_dir)
423 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
425 oldpkg->md5sum = xstrdup(newpkg->md5sum);
426 #if defined HAVE_SHA256
427 if (!oldpkg->sha256sum)
428 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
431 oldpkg->size = xstrdup(newpkg->size);
432 if (!oldpkg->installed_size)
433 oldpkg->installed_size = xstrdup(newpkg->installed_size);
434 if (!oldpkg->priority)
435 oldpkg->priority = xstrdup(newpkg->priority);
437 oldpkg->source = xstrdup(newpkg->source);
438 if (nv_pair_list_empty(&oldpkg->conffiles)){
439 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
440 conffile_list_init(&newpkg->conffiles);
442 if (!oldpkg->installed_files){
443 oldpkg->installed_files = newpkg->installed_files;
444 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
445 newpkg->installed_files = NULL;
447 if (!oldpkg->essential)
448 oldpkg->essential = newpkg->essential;
454 abstract_pkg_init(abstract_pkg_t *ab_pkg)
456 ab_pkg->provided_by = abstract_pkg_vec_alloc();
457 ab_pkg->dependencies_checked = 0;
458 ab_pkg->state_status = SS_NOT_INSTALLED;
462 abstract_pkg_new(void)
464 abstract_pkg_t * ab_pkg;
466 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
467 abstract_pkg_init(ab_pkg);
473 set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
477 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
479 fp = fopen(file_name, "r");
481 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
482 __FUNCTION__, file_name, strerror(errno));
489 if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
490 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
499 pkg_state_want_to_str(pkg_state_want_t sw)
503 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
504 if (pkg_state_want_map[i].value == sw) {
505 return pkg_state_want_map[i].str;
509 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
511 return "<STATE_WANT_UNKNOWN>";
515 pkg_state_want_from_str(char *str)
519 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
520 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
521 return pkg_state_want_map[i].value;
525 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
531 pkg_state_flag_to_str(pkg_state_flag_t sf)
537 /* clear the temporary flags before converting to string */
538 sf &= SF_NONVOLATILE_FLAGS;
541 return xstrdup("ok");
544 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
545 if (sf & pkg_state_flag_map[i].value)
546 len += strlen(pkg_state_flag_map[i].str) + 1;
549 str = xmalloc(len+1);
552 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
553 if (sf & pkg_state_flag_map[i].value) {
554 strncat(str, pkg_state_flag_map[i].str, len);
555 strncat(str, ",", len);
560 str[len-1] = '\0'; /* squash last comma */
566 pkg_state_flag_from_str(const char *str)
571 if (strcmp(str, "ok") == 0) {
574 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
575 const char *sfname = pkg_state_flag_map[i].str;
576 int sfname_len = strlen(sfname);
577 if (strncmp(str, sfname, sfname_len) == 0) {
578 sf |= pkg_state_flag_map[i].value;
592 pkg_state_status_to_str(pkg_state_status_t ss)
596 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
597 if (pkg_state_status_map[i].value == ss) {
598 return pkg_state_status_map[i].str;
602 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
604 return "<STATE_STATUS_UNKNOWN>";
608 pkg_state_status_from_str(const char *str)
612 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
613 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
614 return pkg_state_status_map[i].value;
618 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
620 return SS_NOT_INSTALLED;
624 pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
628 int depends_count = pkg->pre_depends_count +
630 pkg->recommends_count +
633 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
634 goto UNKNOWN_FMT_FIELD;
641 if (strcasecmp(field, "Architecture") == 0) {
642 if (pkg->architecture) {
643 fprintf(fp, "Architecture: %s\n", pkg->architecture);
645 } else if (strcasecmp(field, "Auto-Installed") == 0) {
646 if (pkg->auto_installed)
647 fprintf(fp, "Auto-Installed: yes\n");
649 goto UNKNOWN_FMT_FIELD;
654 if (strcasecmp(field, "Conffiles") == 0) {
655 conffile_list_elt_t *iter;
657 if (nv_pair_list_empty(&pkg->conffiles))
660 fprintf(fp, "Conffiles:\n");
661 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
662 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
663 fprintf(fp, " %s %s\n",
664 ((conffile_t *)iter->data)->name,
665 ((conffile_t *)iter->data)->value);
668 } else if (strcasecmp(field, "Conflicts") == 0) {
670 if (pkg->conflicts_count) {
671 fprintf(fp, "Conflicts:");
672 for(i = 0; i < pkg->conflicts_count; i++) {
673 cdep = pkg->conflicts[i].possibilities[0];
674 fprintf(fp, "%s %s", i == 0 ? "" : ",",
677 fprintf(fp, " (%s%s)",
678 constraint_to_str(cdep->constraint),
685 goto UNKNOWN_FMT_FIELD;
690 if (strcasecmp(field, "Depends") == 0) {
691 if (pkg->depends_count) {
692 fprintf(fp, "Depends:");
693 for (j=0, i=0; i<depends_count; i++) {
694 if (pkg->depends[i].type != DEPEND)
696 str = pkg_depend_str(pkg, i);
697 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
703 } else if (strcasecmp(field, "Description") == 0) {
704 if (pkg->description) {
705 fprintf(fp, "Description: %s\n", pkg->description);
708 goto UNKNOWN_FMT_FIELD;
713 if (pkg->essential) {
714 fprintf(fp, "Essential: yes\n");
720 fprintf(fp, "Filename: %s\n", pkg->filename);
725 if (strcasecmp(field, "Installed-Size") == 0) {
726 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
727 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
728 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
733 if (strcasecmp(field, "Maintainer") == 0) {
734 if (pkg->maintainer) {
735 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
737 } else if (strcasecmp(field, "MD5sum") == 0) {
739 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
742 goto UNKNOWN_FMT_FIELD;
747 if (strcasecmp(field, "Package") == 0) {
748 fprintf(fp, "Package: %s\n", pkg->name);
749 } else if (strcasecmp(field, "Priority") == 0) {
750 fprintf(fp, "Priority: %s\n", pkg->priority);
751 } else if (strcasecmp(field, "Provides") == 0) {
752 if (pkg->provides_count) {
753 fprintf(fp, "Provides:");
754 for(i = 1; i < pkg->provides_count; i++) {
755 fprintf(fp, "%s %s", i == 1 ? "" : ",",
756 pkg->provides[i]->name);
761 goto UNKNOWN_FMT_FIELD;
766 if (strcasecmp (field, "Replaces") == 0) {
767 if (pkg->replaces_count) {
768 fprintf(fp, "Replaces:");
769 for (i = 0; i < pkg->replaces_count; i++) {
770 fprintf(fp, "%s %s", i == 0 ? "" : ",",
771 pkg->replaces[i]->name);
775 } else if (strcasecmp (field, "Recommends") == 0) {
776 if (pkg->recommends_count) {
777 fprintf(fp, "Recommends:");
778 for (j=0, i=0; i<depends_count; i++) {
779 if (pkg->depends[i].type != RECOMMEND)
781 str = pkg_depend_str(pkg, i);
782 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
789 goto UNKNOWN_FMT_FIELD;
794 if (strcasecmp(field, "Section") == 0) {
796 fprintf(fp, "Section: %s\n", pkg->section);
798 #if defined HAVE_SHA256
799 } else if (strcasecmp(field, "SHA256sum") == 0) {
800 if (pkg->sha256sum) {
801 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
804 } else if (strcasecmp(field, "Size") == 0) {
806 fprintf(fp, "Size: %s\n", pkg->size);
808 } else if (strcasecmp(field, "Source") == 0) {
810 fprintf(fp, "Source: %s\n", pkg->source);
812 } else if (strcasecmp(field, "Status") == 0) {
813 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
814 fprintf(fp, "Status: %s %s %s\n",
815 pkg_state_want_to_str(pkg->state_want),
817 pkg_state_status_to_str(pkg->state_status));
819 } else if (strcasecmp(field, "Suggests") == 0) {
820 if (pkg->suggests_count) {
821 fprintf(fp, "Suggests:");
822 for (j=0, i=0; i<depends_count; i++) {
823 if (pkg->depends[i].type != SUGGEST)
825 str = pkg_depend_str(pkg, i);
826 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
833 goto UNKNOWN_FMT_FIELD;
838 if (strcasecmp(field, "Tags") == 0) {
840 fprintf(fp, "Tags: %s\n", pkg->tags);
847 char *version = pkg_version_str_alloc(pkg);
850 fprintf(fp, "Version: %s\n", version);
855 goto UNKNOWN_FMT_FIELD;
861 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
865 pkg_formatted_info(FILE *fp, pkg_t *pkg)
867 pkg_formatted_field(fp, pkg, "Package");
868 pkg_formatted_field(fp, pkg, "Version");
869 pkg_formatted_field(fp, pkg, "Depends");
870 pkg_formatted_field(fp, pkg, "Recommends");
871 pkg_formatted_field(fp, pkg, "Suggests");
872 pkg_formatted_field(fp, pkg, "Provides");
873 pkg_formatted_field(fp, pkg, "Replaces");
874 pkg_formatted_field(fp, pkg, "Conflicts");
875 pkg_formatted_field(fp, pkg, "Status");
876 pkg_formatted_field(fp, pkg, "Section");
877 pkg_formatted_field(fp, pkg, "Essential");
878 pkg_formatted_field(fp, pkg, "Architecture");
879 pkg_formatted_field(fp, pkg, "Maintainer");
880 pkg_formatted_field(fp, pkg, "MD5sum");
881 pkg_formatted_field(fp, pkg, "Size");
882 pkg_formatted_field(fp, pkg, "Filename");
883 pkg_formatted_field(fp, pkg, "Conffiles");
884 pkg_formatted_field(fp, pkg, "Source");
885 pkg_formatted_field(fp, pkg, "Description");
886 pkg_formatted_field(fp, pkg, "Installed-Time");
887 pkg_formatted_field(fp, pkg, "Tags");
892 pkg_print_status(pkg_t * pkg, FILE * file)
898 /* XXX: QUESTION: Do we actually want more fields here? The
899 original idea was to save space by installing only what was
900 needed for actual computation, (package, version, status,
901 essential, conffiles). The assumption is that all other fields
902 can be found in th available file.
904 But, someone proposed the idea to make it possible to
905 reconstruct a .opk from an installed package, (ie. for beaming
906 from one handheld to another). So, maybe we actually want a few
907 more fields here, (depends, suggests, etc.), so that that would
908 be guaranteed to work even in the absence of more information
909 from the available file.
911 28-MAR-03: kergoth and I discussed this yesterday. We think
912 the essential info needs to be here for all installed packages
913 because they may not appear in the Packages files on various
914 feeds. Furthermore, one should be able to install from URL or
915 local storage without requiring a Packages file from any feed.
918 pkg_formatted_field(file, pkg, "Package");
919 pkg_formatted_field(file, pkg, "Version");
920 pkg_formatted_field(file, pkg, "Depends");
921 pkg_formatted_field(file, pkg, "Recommends");
922 pkg_formatted_field(file, pkg, "Suggests");
923 pkg_formatted_field(file, pkg, "Provides");
924 pkg_formatted_field(file, pkg, "Replaces");
925 pkg_formatted_field(file, pkg, "Conflicts");
926 pkg_formatted_field(file, pkg, "Status");
927 pkg_formatted_field(file, pkg, "Essential");
928 pkg_formatted_field(file, pkg, "Architecture");
929 pkg_formatted_field(file, pkg, "Conffiles");
930 pkg_formatted_field(file, pkg, "Installed-Time");
931 pkg_formatted_field(file, pkg, "Auto-Installed");
936 * libdpkg - Debian packaging suite library routines
937 * vercmp.c - comparison of version numbers
939 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
942 /* assume ascii; warning: evaluates x multiple times! */
943 #define order(x) ((x) == '~' ? -1 \
946 : isalpha((x)) ? (x) \
950 verrevcmp(const char *val, const char *ref) {
954 while (*val || *ref) {
957 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
958 int vc= order(*val), rc= order(*ref);
959 if (vc != rc) return vc - rc;
963 while ( *val == '0' ) val++;
964 while ( *ref == '0' ) ref++;
965 while (isdigit(*val) && isdigit(*ref)) {
966 if (!first_diff) first_diff= *val - *ref;
969 if (isdigit(*val)) return 1;
970 if (isdigit(*ref)) return -1;
971 if (first_diff) return first_diff;
977 pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
981 if (pkg->epoch > ref_pkg->epoch) {
985 if (pkg->epoch < ref_pkg->epoch) {
989 r = verrevcmp(pkg->version, ref_pkg->version);
994 r = verrevcmp(pkg->revision, ref_pkg->revision);
1004 pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
1008 r = pkg_compare_versions(it, ref);
1010 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
1014 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
1018 if (strcmp(op, "<<") == 0) {
1022 if (strcmp(op, ">>") == 0) {
1026 if (strcmp(op, "=") == 0) {
1030 fprintf(stderr, "unknown operator: %s", op);
1035 pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
1037 const pkg_t *a = *(const pkg_t**) p1;
1038 const pkg_t *b = *(const pkg_t**) p2;
1041 if (!a->name || !b->name) {
1042 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
1043 a, a->name, b, b->name);
1047 namecmp = strcmp(a->name, b->name);
1050 vercmp = pkg_compare_versions(a, b);
1053 if (!a->arch_priority || !b->arch_priority) {
1054 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
1055 a, a->arch_priority, b, b->arch_priority);
1058 if (a->arch_priority > b->arch_priority)
1060 if (a->arch_priority < b->arch_priority)
1066 abstract_pkg_name_compare(const void *p1, const void *p2)
1068 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1069 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1070 if (!a->name || !b->name) {
1071 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
1072 a, a->name, b, b->name);
1075 return strcmp(a->name, b->name);
1080 pkg_version_str_alloc(pkg_t *pkg)
1086 sprintf_alloc(&version, "%d:%s-%s",
1087 pkg->epoch, pkg->version, pkg->revision);
1089 sprintf_alloc(&version, "%d:%s",
1090 pkg->epoch, pkg->version);
1093 sprintf_alloc(&version, "%s-%s",
1094 pkg->version, pkg->revision);
1096 version = xstrdup(pkg->version);
1103 * XXX: this should be broken into two functions
1106 pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
1109 char *list_file_name = NULL;
1110 FILE *list_file = NULL;
1112 char *installed_file_name;
1115 pkg->installed_files_ref_cnt++;
1117 if (pkg->installed_files) {
1118 return pkg->installed_files;
1121 pkg->installed_files = str_list_alloc();
1123 /* For uninstalled packages, get the file list directly from the package.
1124 For installed packages, look at the package.list file in the database.
1126 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1127 if (pkg->local_filename == NULL) {
1128 return pkg->installed_files;
1130 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1131 file. In other words, change deb_extract so that it can
1132 simply return the file list as a char *[] rather than
1133 insisting on writing in to a FILE * as it does now. */
1134 sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
1135 conf->tmp_dir, pkg->name);
1136 fd = mkstemp(list_file_name);
1138 opkg_message(conf, OPKG_ERROR, "%s: mkstemp(%s): %s",
1139 __FUNCTION__, list_file_name, strerror(errno));
1140 free(list_file_name);
1141 return pkg->installed_files;
1143 list_file = fdopen(fd, "r+");
1144 if (list_file == NULL) {
1145 opkg_message(conf, OPKG_ERROR, "%s: fdopen: %s",
1146 __FUNCTION__, strerror(errno));
1148 unlink(list_file_name);
1149 free(list_file_name);
1150 return pkg->installed_files;
1152 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1154 opkg_message(conf, OPKG_ERROR, "%s: Error extracting file list "
1155 "from %s: %s\n", __FUNCTION__,
1156 pkg->local_filename, strerror(err));
1158 unlink(list_file_name);
1159 free(list_file_name);
1160 return pkg->installed_files;
1164 sprintf_alloc(&list_file_name, "%s/%s.list",
1165 pkg->dest->info_dir, pkg->name);
1166 list_file = fopen(list_file_name, "r");
1167 if (list_file == NULL) {
1168 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
1169 __FUNCTION__, list_file_name, strerror(errno));
1170 free(list_file_name);
1171 return pkg->installed_files;
1173 free(list_file_name);
1176 if (conf->offline_root)
1177 rootdirlen = strlen(conf->offline_root);
1182 line = file_read_line_alloc(list_file);
1188 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1189 if (*file_name == '.') {
1192 if (*file_name == '/') {
1195 sprintf_alloc(&installed_file_name, "%s%s",
1196 pkg->dest->root_dir, file_name);
1198 if (conf->offline_root &&
1199 strncmp(conf->offline_root, file_name, rootdirlen)) {
1200 sprintf_alloc(&installed_file_name, "%s%s",
1201 conf->offline_root, file_name);
1203 // already contains root_dir as header -> ABSOLUTE
1204 sprintf_alloc(&installed_file_name, "%s", file_name);
1207 str_list_append(pkg->installed_files, installed_file_name);
1208 free(installed_file_name);
1214 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1215 unlink(list_file_name);
1216 free(list_file_name);
1219 return pkg->installed_files;
1222 /* XXX: CLEANUP: This function and it's counterpart,
1223 (pkg_get_installed_files), do not match our init/deinit naming
1224 convention. Nor the alloc/free convention. But, then again, neither
1225 of these conventions currrently fit the way these two functions
1228 pkg_free_installed_files(pkg_t *pkg)
1230 pkg->installed_files_ref_cnt--;
1232 if (pkg->installed_files_ref_cnt > 0)
1235 if (pkg->installed_files) {
1236 str_list_purge(pkg->installed_files);
1239 pkg->installed_files = NULL;
1243 pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1245 char *list_file_name;
1247 sprintf_alloc(&list_file_name, "%s/%s.list",
1248 pkg->dest->info_dir, pkg->name);
1250 if (!conf->noaction)
1251 (void)unlink(list_file_name);
1253 free(list_file_name);
1257 pkg_get_conffile(pkg_t *pkg, const char *file_name)
1259 conffile_list_elt_t *iter;
1260 conffile_t *conffile;
1266 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1267 conffile = (conffile_t *)iter->data;
1269 if (strcmp(conffile->name, file_name) == 0) {
1278 pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1279 const char *script, const char *args)
1288 /* XXX: CLEANUP: There must be a better way to handle maintainer
1289 scripts when running with offline_root mode and/or a dest other
1290 than '/'. I've been playing around with some clever chroot
1291 tricks and I might come up with something workable. */
1293 * Attempt to provide a restricted environment for offline operation
1294 * Need the following set as a minimum:
1295 * OPKG_OFFLINE_ROOT = absolute path to root dir
1296 * D = absolute path to root dir (for OE generated postinst)
1297 * PATH = something safe (a restricted set of utilities)
1300 if (conf->offline_root) {
1301 if (conf->offline_root_path) {
1302 setenv("PATH", conf->offline_root_path, 1);
1304 opkg_message(conf, OPKG_NOTICE,
1305 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1308 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1309 setenv("D", conf->offline_root, 1);
1312 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1313 maintainer script within a chroot environment. */
1315 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1316 have scripts in pkg->tmp_unpack_dir. */
1317 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1318 if (pkg->dest == NULL) {
1319 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1320 __FUNCTION__, pkg->name);
1323 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1325 if (pkg->tmp_unpack_dir == NULL) {
1326 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1327 __FUNCTION__, pkg->name);
1330 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1333 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1336 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1338 if (! file_exists(path)) {
1343 sprintf_alloc(&cmd, "%s %s", path, args);
1346 const char *argv[] = {"sh", "-c", cmd, NULL};
1347 err = xsystem(argv);
1352 fprintf(stderr, "%s script returned status %d\n", script, err);
1360 pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1362 nv_pair_list_elt_t *l;
1364 if (!pkg->architecture)
1367 list_for_each_entry(l , &conf->arch_list.head, node) {
1368 nv_pair_t *nv = (nv_pair_t *)l->data;
1369 if (strcmp(nv->name, pkg->architecture) == 0) {
1370 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1375 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1380 pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1382 nv_pair_list_elt_t *l;
1384 list_for_each_entry(l , &conf->arch_list.head, node) {
1385 nv_pair_t *nv = (nv_pair_t *)l->data;
1386 if (strcmp(nv->name, archname) == 0) {
1387 int priority = strtol(nv->value, NULL, 0);
1395 pkg_info_preinstall_check(opkg_conf_t *conf)
1398 hash_table_t *pkg_hash = &conf->pkg_hash;
1399 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1400 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1402 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1403 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1404 /* update arch_priority for each package */
1405 for (i = 0; i < available_pkgs->len; i++) {
1406 pkg_t *pkg = available_pkgs->pkgs[i];
1407 int arch_priority = 1;
1410 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1411 if (pkg->architecture)
1412 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1414 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1415 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1416 pkg->arch_priority = arch_priority;
1419 for (i = 0; i < available_pkgs->len; i++) {
1420 pkg_t *pkg = available_pkgs->pkgs[i];
1421 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1422 /* clear flags and want for any uninstallable package */
1423 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1424 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1425 pkg->state_want = SW_UNKNOWN;
1426 pkg->state_flag = 0;
1429 pkg_vec_free(available_pkgs);
1431 /* update the file owner data structure */
1432 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1433 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1434 for (i = 0; i < installed_pkgs->len; i++) {
1435 pkg_t *pkg = installed_pkgs->pkgs[i];
1436 str_list_t *installed_files = pkg_get_installed_files(conf, pkg); /* this causes installed_files to be cached */
1437 str_list_elt_t *iter, *niter;
1438 if (installed_files == NULL) {
1439 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1442 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1444 iter = niter, niter = str_list_next(installed_files, iter)) {
1445 char *installed_file = (char *) iter->data;
1446 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1447 file_hash_set_file_owner(conf, installed_file, pkg);
1449 pkg_free_installed_files(pkg);
1451 pkg_vec_free(installed_pkgs);
1454 struct pkg_write_filelist_data {
1461 pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1463 struct pkg_write_filelist_data *data = data_;
1464 pkg_t *entry = entry_;
1465 if (entry == data->pkg) {
1466 fprintf(data->stream, "%s\n", key);
1471 pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1473 struct pkg_write_filelist_data data;
1474 char *list_file_name;
1476 sprintf_alloc(&list_file_name, "%s/%s.list",
1477 pkg->dest->info_dir, pkg->name);
1479 opkg_message(conf, OPKG_INFO, "%s: creating %s file for pkg %s\n",
1480 __FUNCTION__, list_file_name, pkg->name);
1482 data.stream = fopen(list_file_name, "w");
1484 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s, \"w\"): %s\n",
1485 __FUNCTION__, list_file_name, strerror(errno));
1486 free(list_file_name);
1492 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1493 fclose(data.stream);
1494 free(list_file_name);
1496 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1502 pkg_write_changed_filelists(opkg_conf_t *conf)
1504 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1505 hash_table_t *pkg_hash = &conf->pkg_hash;
1506 int i, err, ret = 0;
1511 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n",
1514 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1515 for (i = 0; i < installed_pkgs->len; i++) {
1516 pkg_t *pkg = installed_pkgs->pkgs[i];
1517 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1518 err = pkg_write_filelist(conf, pkg);
1524 pkg_vec_free (installed_pkgs);