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);
313 opkg_message(conf, OPKG_ERROR, "Failed to extract control file"
314 " from %s\n", filename);
318 rewind(control_file);
320 if (pkg_parse_from_stream(pkg, control_file, PFM_ALL))
324 fclose(control_file);
326 unlink(control_path);
333 /* Merge any new information in newpkg into oldpkg */
334 /* XXX: CLEANUP: This function shouldn't actually modify anything in
335 newpkg, but should leave it usable. This rework is so that
336 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
338 * uh, i thought that i had originally written this so that it took
339 * two pkgs and returned a new one? we can do that again... -sma
342 pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
344 if (oldpkg == newpkg) {
348 if (!oldpkg->auto_installed)
349 oldpkg->auto_installed = newpkg->auto_installed;
352 oldpkg->src = newpkg->src;
354 oldpkg->dest = newpkg->dest;
355 if (!oldpkg->architecture)
356 oldpkg->architecture = xstrdup(newpkg->architecture);
357 if (!oldpkg->arch_priority)
358 oldpkg->arch_priority = newpkg->arch_priority;
359 if (!oldpkg->section)
360 oldpkg->section = xstrdup(newpkg->section);
361 if(!oldpkg->maintainer)
362 oldpkg->maintainer = xstrdup(newpkg->maintainer);
363 if(!oldpkg->description)
364 oldpkg->description = xstrdup(newpkg->description);
366 /* merge the state_flags from the new package */
367 oldpkg->state_want = newpkg->state_want;
368 oldpkg->state_status = newpkg->state_status;
369 oldpkg->state_flag = newpkg->state_flag;
371 if (oldpkg->state_want == SW_UNKNOWN)
372 oldpkg->state_want = newpkg->state_want;
373 if (oldpkg->state_status == SS_NOT_INSTALLED)
374 oldpkg->state_status = newpkg->state_status;
375 oldpkg->state_flag |= newpkg->state_flag;
378 if (!oldpkg->depends_count && !oldpkg->pre_depends_count && !oldpkg->recommends_count && !oldpkg->suggests_count) {
379 oldpkg->depends_count = newpkg->depends_count;
380 newpkg->depends_count = 0;
382 oldpkg->depends = newpkg->depends;
383 newpkg->depends = NULL;
385 oldpkg->pre_depends_count = newpkg->pre_depends_count;
386 newpkg->pre_depends_count = 0;
388 oldpkg->recommends_count = newpkg->recommends_count;
389 newpkg->recommends_count = 0;
391 oldpkg->suggests_count = newpkg->suggests_count;
392 newpkg->suggests_count = 0;
395 if (oldpkg->provides_count <= 1) {
396 oldpkg->provides_count = newpkg->provides_count;
397 newpkg->provides_count = 0;
399 if (!oldpkg->provides) {
400 oldpkg->provides = newpkg->provides;
401 newpkg->provides = NULL;
405 if (!oldpkg->conflicts_count) {
406 oldpkg->conflicts_count = newpkg->conflicts_count;
407 newpkg->conflicts_count = 0;
409 oldpkg->conflicts = newpkg->conflicts;
410 newpkg->conflicts = NULL;
413 if (!oldpkg->replaces_count) {
414 oldpkg->replaces_count = newpkg->replaces_count;
415 newpkg->replaces_count = 0;
417 oldpkg->replaces = newpkg->replaces;
418 newpkg->replaces = NULL;
421 if (!oldpkg->filename)
422 oldpkg->filename = xstrdup(newpkg->filename);
423 if (!oldpkg->local_filename)
424 oldpkg->local_filename = xstrdup(newpkg->local_filename);
425 if (!oldpkg->tmp_unpack_dir)
426 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
428 oldpkg->md5sum = xstrdup(newpkg->md5sum);
429 #if defined HAVE_SHA256
430 if (!oldpkg->sha256sum)
431 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
434 oldpkg->size = xstrdup(newpkg->size);
435 if (!oldpkg->installed_size)
436 oldpkg->installed_size = xstrdup(newpkg->installed_size);
437 if (!oldpkg->priority)
438 oldpkg->priority = xstrdup(newpkg->priority);
440 oldpkg->source = xstrdup(newpkg->source);
441 if (nv_pair_list_empty(&oldpkg->conffiles)){
442 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
443 conffile_list_init(&newpkg->conffiles);
445 if (!oldpkg->installed_files){
446 oldpkg->installed_files = newpkg->installed_files;
447 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
448 newpkg->installed_files = NULL;
450 if (!oldpkg->essential)
451 oldpkg->essential = newpkg->essential;
457 abstract_pkg_init(abstract_pkg_t *ab_pkg)
459 ab_pkg->provided_by = abstract_pkg_vec_alloc();
460 ab_pkg->dependencies_checked = 0;
461 ab_pkg->state_status = SS_NOT_INSTALLED;
465 abstract_pkg_new(void)
467 abstract_pkg_t * ab_pkg;
469 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
470 abstract_pkg_init(ab_pkg);
476 set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
480 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
482 fp = fopen(file_name, "r");
484 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
485 __FUNCTION__, file_name, strerror(errno));
492 if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
493 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
502 pkg_state_want_to_str(pkg_state_want_t sw)
506 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
507 if (pkg_state_want_map[i].value == sw) {
508 return pkg_state_want_map[i].str;
512 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
514 return "<STATE_WANT_UNKNOWN>";
518 pkg_state_want_from_str(char *str)
522 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
523 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
524 return pkg_state_want_map[i].value;
528 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
534 pkg_state_flag_to_str(pkg_state_flag_t sf)
540 /* clear the temporary flags before converting to string */
541 sf &= SF_NONVOLATILE_FLAGS;
544 return xstrdup("ok");
547 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
548 if (sf & pkg_state_flag_map[i].value)
549 len += strlen(pkg_state_flag_map[i].str) + 1;
552 str = xmalloc(len+1);
555 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
556 if (sf & pkg_state_flag_map[i].value) {
557 strncat(str, pkg_state_flag_map[i].str, len);
558 strncat(str, ",", len);
563 str[len-1] = '\0'; /* squash last comma */
569 pkg_state_flag_from_str(const char *str)
574 if (strcmp(str, "ok") == 0) {
577 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
578 const char *sfname = pkg_state_flag_map[i].str;
579 int sfname_len = strlen(sfname);
580 if (strncmp(str, sfname, sfname_len) == 0) {
581 sf |= pkg_state_flag_map[i].value;
595 pkg_state_status_to_str(pkg_state_status_t ss)
599 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
600 if (pkg_state_status_map[i].value == ss) {
601 return pkg_state_status_map[i].str;
605 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
607 return "<STATE_STATUS_UNKNOWN>";
611 pkg_state_status_from_str(const char *str)
615 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
616 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
617 return pkg_state_status_map[i].value;
621 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
623 return SS_NOT_INSTALLED;
627 pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
631 int depends_count = pkg->pre_depends_count +
633 pkg->recommends_count +
636 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
637 goto UNKNOWN_FMT_FIELD;
644 if (strcasecmp(field, "Architecture") == 0) {
645 if (pkg->architecture) {
646 fprintf(fp, "Architecture: %s\n", pkg->architecture);
648 } else if (strcasecmp(field, "Auto-Installed") == 0) {
649 if (pkg->auto_installed)
650 fprintf(fp, "Auto-Installed: yes\n");
652 goto UNKNOWN_FMT_FIELD;
657 if (strcasecmp(field, "Conffiles") == 0) {
658 conffile_list_elt_t *iter;
660 if (nv_pair_list_empty(&pkg->conffiles))
663 fprintf(fp, "Conffiles:\n");
664 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
665 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
666 fprintf(fp, " %s %s\n",
667 ((conffile_t *)iter->data)->name,
668 ((conffile_t *)iter->data)->value);
671 } else if (strcasecmp(field, "Conflicts") == 0) {
673 if (pkg->conflicts_count) {
674 fprintf(fp, "Conflicts:");
675 for(i = 0; i < pkg->conflicts_count; i++) {
676 cdep = pkg->conflicts[i].possibilities[0];
677 fprintf(fp, "%s %s", i == 0 ? "" : ",",
680 fprintf(fp, " (%s%s)",
681 constraint_to_str(cdep->constraint),
688 goto UNKNOWN_FMT_FIELD;
693 if (strcasecmp(field, "Depends") == 0) {
694 if (pkg->depends_count) {
695 fprintf(fp, "Depends:");
696 for (j=0, i=0; i<depends_count; i++) {
697 if (pkg->depends[i].type != DEPEND)
699 str = pkg_depend_str(pkg, i);
700 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
706 } else if (strcasecmp(field, "Description") == 0) {
707 if (pkg->description) {
708 fprintf(fp, "Description: %s\n", pkg->description);
711 goto UNKNOWN_FMT_FIELD;
716 if (pkg->essential) {
717 fprintf(fp, "Essential: yes\n");
723 fprintf(fp, "Filename: %s\n", pkg->filename);
728 if (strcasecmp(field, "Installed-Size") == 0) {
729 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
730 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
731 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
736 if (strcasecmp(field, "Maintainer") == 0) {
737 if (pkg->maintainer) {
738 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
740 } else if (strcasecmp(field, "MD5sum") == 0) {
742 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
745 goto UNKNOWN_FMT_FIELD;
750 if (strcasecmp(field, "Package") == 0) {
751 fprintf(fp, "Package: %s\n", pkg->name);
752 } else if (strcasecmp(field, "Priority") == 0) {
753 fprintf(fp, "Priority: %s\n", pkg->priority);
754 } else if (strcasecmp(field, "Provides") == 0) {
755 if (pkg->provides_count) {
756 fprintf(fp, "Provides:");
757 for(i = 1; i < pkg->provides_count; i++) {
758 fprintf(fp, "%s %s", i == 1 ? "" : ",",
759 pkg->provides[i]->name);
764 goto UNKNOWN_FMT_FIELD;
769 if (strcasecmp (field, "Replaces") == 0) {
770 if (pkg->replaces_count) {
771 fprintf(fp, "Replaces:");
772 for (i = 0; i < pkg->replaces_count; i++) {
773 fprintf(fp, "%s %s", i == 0 ? "" : ",",
774 pkg->replaces[i]->name);
778 } else if (strcasecmp (field, "Recommends") == 0) {
779 if (pkg->recommends_count) {
780 fprintf(fp, "Recommends:");
781 for (j=0, i=0; i<depends_count; i++) {
782 if (pkg->depends[i].type != RECOMMEND)
784 str = pkg_depend_str(pkg, i);
785 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
792 goto UNKNOWN_FMT_FIELD;
797 if (strcasecmp(field, "Section") == 0) {
799 fprintf(fp, "Section: %s\n", pkg->section);
801 #if defined HAVE_SHA256
802 } else if (strcasecmp(field, "SHA256sum") == 0) {
803 if (pkg->sha256sum) {
804 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
807 } else if (strcasecmp(field, "Size") == 0) {
809 fprintf(fp, "Size: %s\n", pkg->size);
811 } else if (strcasecmp(field, "Source") == 0) {
813 fprintf(fp, "Source: %s\n", pkg->source);
815 } else if (strcasecmp(field, "Status") == 0) {
816 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
817 fprintf(fp, "Status: %s %s %s\n",
818 pkg_state_want_to_str(pkg->state_want),
820 pkg_state_status_to_str(pkg->state_status));
822 } else if (strcasecmp(field, "Suggests") == 0) {
823 if (pkg->suggests_count) {
824 fprintf(fp, "Suggests:");
825 for (j=0, i=0; i<depends_count; i++) {
826 if (pkg->depends[i].type != SUGGEST)
828 str = pkg_depend_str(pkg, i);
829 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
836 goto UNKNOWN_FMT_FIELD;
841 if (strcasecmp(field, "Tags") == 0) {
843 fprintf(fp, "Tags: %s\n", pkg->tags);
850 char *version = pkg_version_str_alloc(pkg);
853 fprintf(fp, "Version: %s\n", version);
858 goto UNKNOWN_FMT_FIELD;
864 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
868 pkg_formatted_info(FILE *fp, pkg_t *pkg)
870 pkg_formatted_field(fp, pkg, "Package");
871 pkg_formatted_field(fp, pkg, "Version");
872 pkg_formatted_field(fp, pkg, "Depends");
873 pkg_formatted_field(fp, pkg, "Recommends");
874 pkg_formatted_field(fp, pkg, "Suggests");
875 pkg_formatted_field(fp, pkg, "Provides");
876 pkg_formatted_field(fp, pkg, "Replaces");
877 pkg_formatted_field(fp, pkg, "Conflicts");
878 pkg_formatted_field(fp, pkg, "Status");
879 pkg_formatted_field(fp, pkg, "Section");
880 pkg_formatted_field(fp, pkg, "Essential");
881 pkg_formatted_field(fp, pkg, "Architecture");
882 pkg_formatted_field(fp, pkg, "Maintainer");
883 pkg_formatted_field(fp, pkg, "MD5sum");
884 pkg_formatted_field(fp, pkg, "Size");
885 pkg_formatted_field(fp, pkg, "Filename");
886 pkg_formatted_field(fp, pkg, "Conffiles");
887 pkg_formatted_field(fp, pkg, "Source");
888 pkg_formatted_field(fp, pkg, "Description");
889 pkg_formatted_field(fp, pkg, "Installed-Time");
890 pkg_formatted_field(fp, pkg, "Tags");
895 pkg_print_status(pkg_t * pkg, FILE * file)
901 /* XXX: QUESTION: Do we actually want more fields here? The
902 original idea was to save space by installing only what was
903 needed for actual computation, (package, version, status,
904 essential, conffiles). The assumption is that all other fields
905 can be found in th available file.
907 But, someone proposed the idea to make it possible to
908 reconstruct a .opk from an installed package, (ie. for beaming
909 from one handheld to another). So, maybe we actually want a few
910 more fields here, (depends, suggests, etc.), so that that would
911 be guaranteed to work even in the absence of more information
912 from the available file.
914 28-MAR-03: kergoth and I discussed this yesterday. We think
915 the essential info needs to be here for all installed packages
916 because they may not appear in the Packages files on various
917 feeds. Furthermore, one should be able to install from URL or
918 local storage without requiring a Packages file from any feed.
921 pkg_formatted_field(file, pkg, "Package");
922 pkg_formatted_field(file, pkg, "Version");
923 pkg_formatted_field(file, pkg, "Depends");
924 pkg_formatted_field(file, pkg, "Recommends");
925 pkg_formatted_field(file, pkg, "Suggests");
926 pkg_formatted_field(file, pkg, "Provides");
927 pkg_formatted_field(file, pkg, "Replaces");
928 pkg_formatted_field(file, pkg, "Conflicts");
929 pkg_formatted_field(file, pkg, "Status");
930 pkg_formatted_field(file, pkg, "Essential");
931 pkg_formatted_field(file, pkg, "Architecture");
932 pkg_formatted_field(file, pkg, "Conffiles");
933 pkg_formatted_field(file, pkg, "Installed-Time");
934 pkg_formatted_field(file, pkg, "Auto-Installed");
939 * libdpkg - Debian packaging suite library routines
940 * vercmp.c - comparison of version numbers
942 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
945 /* assume ascii; warning: evaluates x multiple times! */
946 #define order(x) ((x) == '~' ? -1 \
949 : isalpha((x)) ? (x) \
953 verrevcmp(const char *val, const char *ref) {
957 while (*val || *ref) {
960 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
961 int vc= order(*val), rc= order(*ref);
962 if (vc != rc) return vc - rc;
966 while ( *val == '0' ) val++;
967 while ( *ref == '0' ) ref++;
968 while (isdigit(*val) && isdigit(*ref)) {
969 if (!first_diff) first_diff= *val - *ref;
972 if (isdigit(*val)) return 1;
973 if (isdigit(*ref)) return -1;
974 if (first_diff) return first_diff;
980 pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
984 if (pkg->epoch > ref_pkg->epoch) {
988 if (pkg->epoch < ref_pkg->epoch) {
992 r = verrevcmp(pkg->version, ref_pkg->version);
997 r = verrevcmp(pkg->revision, ref_pkg->revision);
1007 pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
1011 r = pkg_compare_versions(it, ref);
1013 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
1017 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
1021 if (strcmp(op, "<<") == 0) {
1025 if (strcmp(op, ">>") == 0) {
1029 if (strcmp(op, "=") == 0) {
1033 fprintf(stderr, "unknown operator: %s", op);
1038 pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
1040 const pkg_t *a = *(const pkg_t**) p1;
1041 const pkg_t *b = *(const pkg_t**) p2;
1044 if (!a->name || !b->name) {
1045 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
1046 a, a->name, b, b->name);
1050 namecmp = strcmp(a->name, b->name);
1053 vercmp = pkg_compare_versions(a, b);
1056 if (!a->arch_priority || !b->arch_priority) {
1057 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
1058 a, a->arch_priority, b, b->arch_priority);
1061 if (a->arch_priority > b->arch_priority)
1063 if (a->arch_priority < b->arch_priority)
1069 abstract_pkg_name_compare(const void *p1, const void *p2)
1071 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
1072 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
1073 if (!a->name || !b->name) {
1074 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
1075 a, a->name, b, b->name);
1078 return strcmp(a->name, b->name);
1083 pkg_version_str_alloc(pkg_t *pkg)
1089 sprintf_alloc(&version, "%d:%s-%s",
1090 pkg->epoch, pkg->version, pkg->revision);
1092 sprintf_alloc(&version, "%d:%s",
1093 pkg->epoch, pkg->version);
1096 sprintf_alloc(&version, "%s-%s",
1097 pkg->version, pkg->revision);
1099 version = xstrdup(pkg->version);
1106 * XXX: this should be broken into two functions
1109 pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
1112 char *list_file_name = NULL;
1113 FILE *list_file = NULL;
1115 char *installed_file_name;
1118 pkg->installed_files_ref_cnt++;
1120 if (pkg->installed_files) {
1121 return pkg->installed_files;
1124 pkg->installed_files = str_list_alloc();
1126 /* For uninstalled packages, get the file list directly from the package.
1127 For installed packages, look at the package.list file in the database.
1129 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1130 if (pkg->local_filename == NULL) {
1131 return pkg->installed_files;
1133 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1134 file. In other words, change deb_extract so that it can
1135 simply return the file list as a char *[] rather than
1136 insisting on writing in to a FILE * as it does now. */
1137 sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
1138 conf->tmp_dir, pkg->name);
1139 fd = mkstemp(list_file_name);
1141 opkg_message(conf, OPKG_ERROR, "%s: mkstemp(%s): %s",
1142 __FUNCTION__, list_file_name, strerror(errno));
1143 free(list_file_name);
1144 return pkg->installed_files;
1146 list_file = fdopen(fd, "r+");
1147 if (list_file == NULL) {
1148 opkg_message(conf, OPKG_ERROR, "%s: fdopen: %s",
1149 __FUNCTION__, strerror(errno));
1151 unlink(list_file_name);
1152 free(list_file_name);
1153 return pkg->installed_files;
1155 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1157 opkg_message(conf, OPKG_ERROR, "%s: Error extracting file list "
1158 "from %s\n", __FUNCTION__,
1159 pkg->local_filename);
1161 unlink(list_file_name);
1162 free(list_file_name);
1163 str_list_deinit(pkg->installed_files);
1164 pkg->installed_files = NULL;
1169 sprintf_alloc(&list_file_name, "%s/%s.list",
1170 pkg->dest->info_dir, pkg->name);
1171 list_file = fopen(list_file_name, "r");
1172 if (list_file == NULL) {
1173 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
1174 __FUNCTION__, list_file_name, strerror(errno));
1175 free(list_file_name);
1176 return pkg->installed_files;
1178 free(list_file_name);
1181 if (conf->offline_root)
1182 rootdirlen = strlen(conf->offline_root);
1187 line = file_read_line_alloc(list_file);
1193 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1194 if (*file_name == '.') {
1197 if (*file_name == '/') {
1200 sprintf_alloc(&installed_file_name, "%s%s",
1201 pkg->dest->root_dir, file_name);
1203 if (conf->offline_root &&
1204 strncmp(conf->offline_root, file_name, rootdirlen)) {
1205 sprintf_alloc(&installed_file_name, "%s%s",
1206 conf->offline_root, file_name);
1208 // already contains root_dir as header -> ABSOLUTE
1209 sprintf_alloc(&installed_file_name, "%s", file_name);
1212 str_list_append(pkg->installed_files, installed_file_name);
1213 free(installed_file_name);
1219 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1220 unlink(list_file_name);
1221 free(list_file_name);
1224 return pkg->installed_files;
1227 /* XXX: CLEANUP: This function and it's counterpart,
1228 (pkg_get_installed_files), do not match our init/deinit naming
1229 convention. Nor the alloc/free convention. But, then again, neither
1230 of these conventions currrently fit the way these two functions
1233 pkg_free_installed_files(pkg_t *pkg)
1235 pkg->installed_files_ref_cnt--;
1237 if (pkg->installed_files_ref_cnt > 0)
1240 if (pkg->installed_files) {
1241 str_list_purge(pkg->installed_files);
1244 pkg->installed_files = NULL;
1248 pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1250 char *list_file_name;
1252 sprintf_alloc(&list_file_name, "%s/%s.list",
1253 pkg->dest->info_dir, pkg->name);
1255 if (!conf->noaction)
1256 (void)unlink(list_file_name);
1258 free(list_file_name);
1262 pkg_get_conffile(pkg_t *pkg, const char *file_name)
1264 conffile_list_elt_t *iter;
1265 conffile_t *conffile;
1271 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1272 conffile = (conffile_t *)iter->data;
1274 if (strcmp(conffile->name, file_name) == 0) {
1283 pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1284 const char *script, const char *args)
1293 /* XXX: CLEANUP: There must be a better way to handle maintainer
1294 scripts when running with offline_root mode and/or a dest other
1295 than '/'. I've been playing around with some clever chroot
1296 tricks and I might come up with something workable. */
1298 * Attempt to provide a restricted environment for offline operation
1299 * Need the following set as a minimum:
1300 * OPKG_OFFLINE_ROOT = absolute path to root dir
1301 * D = absolute path to root dir (for OE generated postinst)
1302 * PATH = something safe (a restricted set of utilities)
1305 if (conf->offline_root) {
1306 if (conf->offline_root_path) {
1307 setenv("PATH", conf->offline_root_path, 1);
1309 opkg_message(conf, OPKG_NOTICE,
1310 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1313 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1314 setenv("D", conf->offline_root, 1);
1317 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1318 maintainer script within a chroot environment. */
1320 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1321 have scripts in pkg->tmp_unpack_dir. */
1322 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1323 if (pkg->dest == NULL) {
1324 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1325 __FUNCTION__, pkg->name);
1328 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1330 if (pkg->tmp_unpack_dir == NULL) {
1331 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1332 __FUNCTION__, pkg->name);
1335 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1338 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1341 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1343 if (! file_exists(path)) {
1348 sprintf_alloc(&cmd, "%s %s", path, args);
1351 const char *argv[] = {"sh", "-c", cmd, NULL};
1352 err = xsystem(argv);
1357 fprintf(stderr, "%s script returned status %d\n", script, err);
1365 pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1367 nv_pair_list_elt_t *l;
1369 if (!pkg->architecture)
1372 list_for_each_entry(l , &conf->arch_list.head, node) {
1373 nv_pair_t *nv = (nv_pair_t *)l->data;
1374 if (strcmp(nv->name, pkg->architecture) == 0) {
1375 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1380 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1385 pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1387 nv_pair_list_elt_t *l;
1389 list_for_each_entry(l , &conf->arch_list.head, node) {
1390 nv_pair_t *nv = (nv_pair_t *)l->data;
1391 if (strcmp(nv->name, archname) == 0) {
1392 int priority = strtol(nv->value, NULL, 0);
1400 pkg_info_preinstall_check(opkg_conf_t *conf)
1403 hash_table_t *pkg_hash = &conf->pkg_hash;
1404 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1405 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1407 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1408 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1409 /* update arch_priority for each package */
1410 for (i = 0; i < available_pkgs->len; i++) {
1411 pkg_t *pkg = available_pkgs->pkgs[i];
1412 int arch_priority = 1;
1415 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1416 if (pkg->architecture)
1417 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1419 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1420 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1421 pkg->arch_priority = arch_priority;
1424 for (i = 0; i < available_pkgs->len; i++) {
1425 pkg_t *pkg = available_pkgs->pkgs[i];
1426 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1427 /* clear flags and want for any uninstallable package */
1428 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1429 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1430 pkg->state_want = SW_UNKNOWN;
1431 pkg->state_flag = 0;
1434 pkg_vec_free(available_pkgs);
1436 /* update the file owner data structure */
1437 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1438 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1439 for (i = 0; i < installed_pkgs->len; i++) {
1440 pkg_t *pkg = installed_pkgs->pkgs[i];
1441 str_list_t *installed_files = pkg_get_installed_files(conf, pkg); /* this causes installed_files to be cached */
1442 str_list_elt_t *iter, *niter;
1443 if (installed_files == NULL) {
1444 opkg_message(conf, OPKG_ERROR, "Failed to determine installed "
1445 "files for pkg %s.\n", pkg->name);
1448 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1450 iter = niter, niter = str_list_next(installed_files, iter)) {
1451 char *installed_file = (char *) iter->data;
1452 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1453 file_hash_set_file_owner(conf, installed_file, pkg);
1455 pkg_free_installed_files(pkg);
1457 pkg_vec_free(installed_pkgs);
1460 struct pkg_write_filelist_data {
1467 pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1469 struct pkg_write_filelist_data *data = data_;
1470 pkg_t *entry = entry_;
1471 if (entry == data->pkg) {
1472 fprintf(data->stream, "%s\n", key);
1477 pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1479 struct pkg_write_filelist_data data;
1480 char *list_file_name;
1482 sprintf_alloc(&list_file_name, "%s/%s.list",
1483 pkg->dest->info_dir, pkg->name);
1485 opkg_message(conf, OPKG_INFO, "%s: creating %s file for pkg %s\n",
1486 __FUNCTION__, list_file_name, pkg->name);
1488 data.stream = fopen(list_file_name, "w");
1490 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s, \"w\"): %s\n",
1491 __FUNCTION__, list_file_name, strerror(errno));
1492 free(list_file_name);
1498 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1499 fclose(data.stream);
1500 free(list_file_name);
1502 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1508 pkg_write_changed_filelists(opkg_conf_t *conf)
1510 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1511 hash_table_t *pkg_hash = &conf->pkg_hash;
1512 int i, err, ret = 0;
1517 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n",
1520 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1521 for (i = 0; i < installed_pkgs->len; i++) {
1522 pkg_t *pkg = installed_pkgs->pkgs[i];
1523 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1524 err = pkg_write_filelist(conf, pkg);
1530 pkg_vec_free (installed_pkgs);