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);
317 pkg_parse_from_stream(pkg, control_file, PFM_ALL);
320 fclose(control_file);
322 unlink(control_path);
329 /* Merge any new information in newpkg into oldpkg */
330 /* XXX: CLEANUP: This function shouldn't actually modify anything in
331 newpkg, but should leave it usable. This rework is so that
332 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
334 * uh, i thought that i had originally written this so that it took
335 * two pkgs and returned a new one? we can do that again... -sma
338 pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
340 if (oldpkg == newpkg) {
344 if (!oldpkg->auto_installed)
345 oldpkg->auto_installed = newpkg->auto_installed;
348 oldpkg->src = newpkg->src;
350 oldpkg->dest = newpkg->dest;
351 if (!oldpkg->architecture)
352 oldpkg->architecture = xstrdup(newpkg->architecture);
353 if (!oldpkg->arch_priority)
354 oldpkg->arch_priority = newpkg->arch_priority;
355 if (!oldpkg->section)
356 oldpkg->section = xstrdup(newpkg->section);
357 if(!oldpkg->maintainer)
358 oldpkg->maintainer = xstrdup(newpkg->maintainer);
359 if(!oldpkg->description)
360 oldpkg->description = xstrdup(newpkg->description);
362 /* merge the state_flags from the new package */
363 oldpkg->state_want = newpkg->state_want;
364 oldpkg->state_status = newpkg->state_status;
365 oldpkg->state_flag = newpkg->state_flag;
367 if (oldpkg->state_want == SW_UNKNOWN)
368 oldpkg->state_want = newpkg->state_want;
369 if (oldpkg->state_status == SS_NOT_INSTALLED)
370 oldpkg->state_status = newpkg->state_status;
371 oldpkg->state_flag |= newpkg->state_flag;
374 if (!oldpkg->depends_count && !oldpkg->pre_depends_count && !oldpkg->recommends_count && !oldpkg->suggests_count) {
375 oldpkg->depends_count = newpkg->depends_count;
376 newpkg->depends_count = 0;
378 oldpkg->depends = newpkg->depends;
379 newpkg->depends = NULL;
381 oldpkg->pre_depends_count = newpkg->pre_depends_count;
382 newpkg->pre_depends_count = 0;
384 oldpkg->recommends_count = newpkg->recommends_count;
385 newpkg->recommends_count = 0;
387 oldpkg->suggests_count = newpkg->suggests_count;
388 newpkg->suggests_count = 0;
391 if (oldpkg->provides_count <= 1) {
392 oldpkg->provides_count = newpkg->provides_count;
393 newpkg->provides_count = 0;
395 if (!oldpkg->provides) {
396 oldpkg->provides = newpkg->provides;
397 newpkg->provides = NULL;
401 if (!oldpkg->conflicts_count) {
402 oldpkg->conflicts_count = newpkg->conflicts_count;
403 newpkg->conflicts_count = 0;
405 oldpkg->conflicts = newpkg->conflicts;
406 newpkg->conflicts = NULL;
409 if (!oldpkg->replaces_count) {
410 oldpkg->replaces_count = newpkg->replaces_count;
411 newpkg->replaces_count = 0;
413 oldpkg->replaces = newpkg->replaces;
414 newpkg->replaces = NULL;
417 if (!oldpkg->filename)
418 oldpkg->filename = xstrdup(newpkg->filename);
419 if (!oldpkg->local_filename)
420 oldpkg->local_filename = xstrdup(newpkg->local_filename);
421 if (!oldpkg->tmp_unpack_dir)
422 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
424 oldpkg->md5sum = xstrdup(newpkg->md5sum);
425 #if defined HAVE_SHA256
426 if (!oldpkg->sha256sum)
427 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
430 oldpkg->size = xstrdup(newpkg->size);
431 if (!oldpkg->installed_size)
432 oldpkg->installed_size = xstrdup(newpkg->installed_size);
433 if (!oldpkg->priority)
434 oldpkg->priority = xstrdup(newpkg->priority);
436 oldpkg->source = xstrdup(newpkg->source);
437 if (nv_pair_list_empty(&oldpkg->conffiles)){
438 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
439 conffile_list_init(&newpkg->conffiles);
441 if (!oldpkg->installed_files){
442 oldpkg->installed_files = newpkg->installed_files;
443 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
444 newpkg->installed_files = NULL;
446 if (!oldpkg->essential)
447 oldpkg->essential = newpkg->essential;
453 abstract_pkg_init(abstract_pkg_t *ab_pkg)
455 ab_pkg->provided_by = abstract_pkg_vec_alloc();
456 ab_pkg->dependencies_checked = 0;
457 ab_pkg->state_status = SS_NOT_INSTALLED;
461 abstract_pkg_new(void)
463 abstract_pkg_t * ab_pkg;
465 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
466 abstract_pkg_init(ab_pkg);
472 set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
476 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
478 fp = fopen(file_name, "r");
480 opkg_message(conf, OPKG_ERROR, "fopen(%s): %s\n",
481 file_name, strerror(errno));
488 if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
489 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
498 pkg_state_want_to_str(pkg_state_want_t sw)
502 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
503 if (pkg_state_want_map[i].value == sw) {
504 return pkg_state_want_map[i].str;
508 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
510 return "<STATE_WANT_UNKNOWN>";
514 pkg_state_want_from_str(char *str)
518 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
519 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
520 return pkg_state_want_map[i].value;
524 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
530 pkg_state_flag_to_str(pkg_state_flag_t sf)
536 /* clear the temporary flags before converting to string */
537 sf &= SF_NONVOLATILE_FLAGS;
540 return xstrdup("ok");
543 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
544 if (sf & pkg_state_flag_map[i].value)
545 len += strlen(pkg_state_flag_map[i].str) + 1;
548 str = xmalloc(len+1);
551 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
552 if (sf & pkg_state_flag_map[i].value) {
553 strncat(str, pkg_state_flag_map[i].str, len);
554 strncat(str, ",", len);
559 str[len-1] = '\0'; /* squash last comma */
565 pkg_state_flag_from_str(const char *str)
570 if (strcmp(str, "ok") == 0) {
573 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
574 const char *sfname = pkg_state_flag_map[i].str;
575 int sfname_len = strlen(sfname);
576 if (strncmp(str, sfname, sfname_len) == 0) {
577 sf |= pkg_state_flag_map[i].value;
591 pkg_state_status_to_str(pkg_state_status_t ss)
595 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
596 if (pkg_state_status_map[i].value == ss) {
597 return pkg_state_status_map[i].str;
601 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
603 return "<STATE_STATUS_UNKNOWN>";
607 pkg_state_status_from_str(const char *str)
611 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
612 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
613 return pkg_state_status_map[i].value;
617 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
619 return SS_NOT_INSTALLED;
623 pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
627 int depends_count = pkg->pre_depends_count +
629 pkg->recommends_count +
632 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
633 goto UNKNOWN_FMT_FIELD;
640 if (strcasecmp(field, "Architecture") == 0) {
641 if (pkg->architecture) {
642 fprintf(fp, "Architecture: %s\n", pkg->architecture);
644 } else if (strcasecmp(field, "Auto-Installed") == 0) {
645 if (pkg->auto_installed)
646 fprintf(fp, "Auto-Installed: yes\n");
648 goto UNKNOWN_FMT_FIELD;
653 if (strcasecmp(field, "Conffiles") == 0) {
654 conffile_list_elt_t *iter;
656 if (nv_pair_list_empty(&pkg->conffiles))
659 fprintf(fp, "Conffiles:\n");
660 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
661 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
662 fprintf(fp, " %s %s\n",
663 ((conffile_t *)iter->data)->name,
664 ((conffile_t *)iter->data)->value);
667 } else if (strcasecmp(field, "Conflicts") == 0) {
669 if (pkg->conflicts_count) {
670 fprintf(fp, "Conflicts:");
671 for(i = 0; i < pkg->conflicts_count; i++) {
672 cdep = pkg->conflicts[i].possibilities[0];
673 fprintf(fp, "%s %s", i == 0 ? "" : ",",
676 fprintf(fp, " (%s%s)",
677 constraint_to_str(cdep->constraint),
684 goto UNKNOWN_FMT_FIELD;
689 if (strcasecmp(field, "Depends") == 0) {
690 if (pkg->depends_count) {
691 fprintf(fp, "Depends:");
692 for (j=0, i=0; i<depends_count; i++) {
693 if (pkg->depends[i].type != DEPEND)
695 str = pkg_depend_str(pkg, i);
696 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
702 } else if (strcasecmp(field, "Description") == 0) {
703 if (pkg->description) {
704 fprintf(fp, "Description: %s\n", pkg->description);
707 goto UNKNOWN_FMT_FIELD;
712 if (pkg->essential) {
713 fprintf(fp, "Essential: yes\n");
719 fprintf(fp, "Filename: %s\n", pkg->filename);
724 if (strcasecmp(field, "Installed-Size") == 0) {
725 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
726 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
727 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
732 if (strcasecmp(field, "Maintainer") == 0) {
733 if (pkg->maintainer) {
734 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
736 } else if (strcasecmp(field, "MD5sum") == 0) {
738 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
741 goto UNKNOWN_FMT_FIELD;
746 if (strcasecmp(field, "Package") == 0) {
747 fprintf(fp, "Package: %s\n", pkg->name);
748 } else if (strcasecmp(field, "Priority") == 0) {
749 fprintf(fp, "Priority: %s\n", pkg->priority);
750 } else if (strcasecmp(field, "Provides") == 0) {
751 if (pkg->provides_count) {
752 fprintf(fp, "Provides:");
753 for(i = 1; i < pkg->provides_count; i++) {
754 fprintf(fp, "%s %s", i == 1 ? "" : ",",
755 pkg->provides[i]->name);
760 goto UNKNOWN_FMT_FIELD;
765 if (strcasecmp (field, "Replaces") == 0) {
766 if (pkg->replaces_count) {
767 fprintf(fp, "Replaces:");
768 for (i = 0; i < pkg->replaces_count; i++) {
769 fprintf(fp, "%s %s", i == 0 ? "" : ",",
770 pkg->replaces[i]->name);
774 } else if (strcasecmp (field, "Recommends") == 0) {
775 if (pkg->recommends_count) {
776 fprintf(fp, "Recommends:");
777 for (j=0, i=0; i<depends_count; i++) {
778 if (pkg->depends[i].type != RECOMMEND)
780 str = pkg_depend_str(pkg, i);
781 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
788 goto UNKNOWN_FMT_FIELD;
793 if (strcasecmp(field, "Section") == 0) {
795 fprintf(fp, "Section: %s\n", pkg->section);
797 #if defined HAVE_SHA256
798 } else if (strcasecmp(field, "SHA256sum") == 0) {
799 if (pkg->sha256sum) {
800 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
803 } else if (strcasecmp(field, "Size") == 0) {
805 fprintf(fp, "Size: %s\n", pkg->size);
807 } else if (strcasecmp(field, "Source") == 0) {
809 fprintf(fp, "Source: %s\n", pkg->source);
811 } else if (strcasecmp(field, "Status") == 0) {
812 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
813 fprintf(fp, "Status: %s %s %s\n",
814 pkg_state_want_to_str(pkg->state_want),
816 pkg_state_status_to_str(pkg->state_status));
818 } else if (strcasecmp(field, "Suggests") == 0) {
819 if (pkg->suggests_count) {
820 fprintf(fp, "Suggests:");
821 for (j=0, i=0; i<depends_count; i++) {
822 if (pkg->depends[i].type != SUGGEST)
824 str = pkg_depend_str(pkg, i);
825 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
832 goto UNKNOWN_FMT_FIELD;
837 if (strcasecmp(field, "Tags") == 0) {
839 fprintf(fp, "Tags: %s\n", pkg->tags);
846 char *version = pkg_version_str_alloc(pkg);
849 fprintf(fp, "Version: %s\n", version);
854 goto UNKNOWN_FMT_FIELD;
860 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
864 pkg_formatted_info(FILE *fp, pkg_t *pkg)
866 pkg_formatted_field(fp, pkg, "Package");
867 pkg_formatted_field(fp, pkg, "Version");
868 pkg_formatted_field(fp, pkg, "Depends");
869 pkg_formatted_field(fp, pkg, "Recommends");
870 pkg_formatted_field(fp, pkg, "Suggests");
871 pkg_formatted_field(fp, pkg, "Provides");
872 pkg_formatted_field(fp, pkg, "Replaces");
873 pkg_formatted_field(fp, pkg, "Conflicts");
874 pkg_formatted_field(fp, pkg, "Status");
875 pkg_formatted_field(fp, pkg, "Section");
876 pkg_formatted_field(fp, pkg, "Essential");
877 pkg_formatted_field(fp, pkg, "Architecture");
878 pkg_formatted_field(fp, pkg, "Maintainer");
879 pkg_formatted_field(fp, pkg, "MD5sum");
880 pkg_formatted_field(fp, pkg, "Size");
881 pkg_formatted_field(fp, pkg, "Filename");
882 pkg_formatted_field(fp, pkg, "Conffiles");
883 pkg_formatted_field(fp, pkg, "Source");
884 pkg_formatted_field(fp, pkg, "Description");
885 pkg_formatted_field(fp, pkg, "Installed-Time");
886 pkg_formatted_field(fp, pkg, "Tags");
891 pkg_print_status(pkg_t * pkg, FILE * file)
897 /* XXX: QUESTION: Do we actually want more fields here? The
898 original idea was to save space by installing only what was
899 needed for actual computation, (package, version, status,
900 essential, conffiles). The assumption is that all other fields
901 can be found in th available file.
903 But, someone proposed the idea to make it possible to
904 reconstruct a .opk from an installed package, (ie. for beaming
905 from one handheld to another). So, maybe we actually want a few
906 more fields here, (depends, suggests, etc.), so that that would
907 be guaranteed to work even in the absence of more information
908 from the available file.
910 28-MAR-03: kergoth and I discussed this yesterday. We think
911 the essential info needs to be here for all installed packages
912 because they may not appear in the Packages files on various
913 feeds. Furthermore, one should be able to install from URL or
914 local storage without requiring a Packages file from any feed.
917 pkg_formatted_field(file, pkg, "Package");
918 pkg_formatted_field(file, pkg, "Version");
919 pkg_formatted_field(file, pkg, "Depends");
920 pkg_formatted_field(file, pkg, "Recommends");
921 pkg_formatted_field(file, pkg, "Suggests");
922 pkg_formatted_field(file, pkg, "Provides");
923 pkg_formatted_field(file, pkg, "Replaces");
924 pkg_formatted_field(file, pkg, "Conflicts");
925 pkg_formatted_field(file, pkg, "Status");
926 pkg_formatted_field(file, pkg, "Essential");
927 pkg_formatted_field(file, pkg, "Architecture");
928 pkg_formatted_field(file, pkg, "Conffiles");
929 pkg_formatted_field(file, pkg, "Installed-Time");
930 pkg_formatted_field(file, pkg, "Auto-Installed");
935 * libdpkg - Debian packaging suite library routines
936 * vercmp.c - comparison of version numbers
938 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
941 /* assume ascii; warning: evaluates x multiple times! */
942 #define order(x) ((x) == '~' ? -1 \
945 : isalpha((x)) ? (x) \
949 verrevcmp(const char *val, const char *ref) {
953 while (*val || *ref) {
956 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
957 int vc= order(*val), rc= order(*ref);
958 if (vc != rc) return vc - rc;
962 while ( *val == '0' ) val++;
963 while ( *ref == '0' ) ref++;
964 while (isdigit(*val) && isdigit(*ref)) {
965 if (!first_diff) first_diff= *val - *ref;
968 if (isdigit(*val)) return 1;
969 if (isdigit(*ref)) return -1;
970 if (first_diff) return first_diff;
976 pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
980 if (pkg->epoch > ref_pkg->epoch) {
984 if (pkg->epoch < ref_pkg->epoch) {
988 r = verrevcmp(pkg->version, ref_pkg->version);
993 r = verrevcmp(pkg->revision, ref_pkg->revision);
1003 pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
1007 r = pkg_compare_versions(it, ref);
1009 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
1013 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
1017 if (strcmp(op, "<<") == 0) {
1021 if (strcmp(op, ">>") == 0) {
1025 if (strcmp(op, "=") == 0) {
1029 fprintf(stderr, "unknown operator: %s", op);
1034 pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
1036 const pkg_t *a = *(const pkg_t**) p1;
1037 const pkg_t *b = *(const pkg_t**) p2;
1040 if (!a->name || !b->name) {
1041 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
1042 a, a->name, b, b->name);
1046 namecmp = strcmp(a->name, b->name);
1049 vercmp = pkg_compare_versions(a, b);
1052 if (!a->arch_priority || !b->arch_priority) {
1053 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
1054 a, a->arch_priority, b, b->arch_priority);
1057 if (a->arch_priority > b->arch_priority)
1059 if (a->arch_priority < b->arch_priority)
1065 abstract_pkg_name_compare(const void *p1, const void *p2)
1067 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1068 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1069 if (!a->name || !b->name) {
1070 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
1071 a, a->name, b, b->name);
1074 return strcmp(a->name, b->name);
1079 pkg_version_str_alloc(pkg_t *pkg)
1085 sprintf_alloc(&version, "%d:%s-%s",
1086 pkg->epoch, pkg->version, pkg->revision);
1088 sprintf_alloc(&version, "%d:%s",
1089 pkg->epoch, pkg->version);
1092 sprintf_alloc(&version, "%s-%s",
1093 pkg->version, pkg->revision);
1095 version = xstrdup(pkg->version);
1102 * XXX: this should be broken into two functions
1105 pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
1108 char *list_file_name = NULL;
1109 FILE *list_file = NULL;
1111 char *installed_file_name;
1114 pkg->installed_files_ref_cnt++;
1116 if (pkg->installed_files) {
1117 return pkg->installed_files;
1120 pkg->installed_files = str_list_alloc();
1122 /* For uninstalled packages, get the file list directly from the package.
1123 For installed packages, look at the package.list file in the database.
1125 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1126 if (pkg->local_filename == NULL) {
1127 return pkg->installed_files;
1129 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1130 file. In other words, change deb_extract so that it can
1131 simply return the file list as a char *[] rather than
1132 insisting on writing in to a FILE * as it does now. */
1133 sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
1134 conf->tmp_dir, pkg->name);
1135 fd = mkstemp(list_file_name);
1137 opkg_message(conf, OPKG_ERROR, "%s: mkstemp(%s): %s",
1138 __FUNCTION__, list_file_name, strerror(errno));
1139 free(list_file_name);
1140 return pkg->installed_files;
1142 list_file = fdopen(fd, "r+");
1143 if (list_file == NULL) {
1144 opkg_message(conf, OPKG_ERROR, "%s: fdopen: %s",
1145 __FUNCTION__, strerror(errno));
1147 unlink(list_file_name);
1148 free(list_file_name);
1149 return pkg->installed_files;
1151 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1153 opkg_message(conf, OPKG_ERROR, "%s: Error extracting file list "
1154 "from %s: %s\n", __FUNCTION__,
1155 pkg->local_filename, strerror(err));
1157 unlink(list_file_name);
1158 free(list_file_name);
1159 return pkg->installed_files;
1163 sprintf_alloc(&list_file_name, "%s/%s.list",
1164 pkg->dest->info_dir, pkg->name);
1165 list_file = fopen(list_file_name, "r");
1166 if (list_file == NULL) {
1167 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
1168 __FUNCTION__, list_file_name, strerror(errno));
1169 free(list_file_name);
1170 return pkg->installed_files;
1172 free(list_file_name);
1175 if (conf->offline_root)
1176 rootdirlen = strlen(conf->offline_root);
1181 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);