1 /* pkg.c - the opkg package management system
5 Copyright (C) 2001 University of Southern California
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
27 #include "pkg_parse.h"
28 #include "pkg_extract.h"
29 #include "opkg_message.h"
30 #include "opkg_utils.h"
32 #include "libbb/libbb.h"
33 #include "sprintf_alloc.h"
34 #include "file_util.h"
37 #include "opkg_conf.h"
39 typedef struct enum_map enum_map_t;
46 static const enum_map_t pkg_state_want_map[] = {
47 { SW_UNKNOWN, "unknown"},
48 { SW_INSTALL, "install"},
49 { SW_DEINSTALL, "deinstall"},
53 static const enum_map_t pkg_state_flag_map[] = {
55 { SF_REINSTREQ, "reinstreq"},
57 { SF_REPLACE, "replace"},
58 { SF_NOPRUNE, "noprune"},
59 { SF_PREFER, "prefer"},
60 { SF_OBSOLETE, "obsolete"},
64 static const enum_map_t pkg_state_status_map[] = {
65 { SS_NOT_INSTALLED, "not-installed" },
66 { SS_UNPACKED, "unpacked" },
67 { SS_HALF_CONFIGURED, "half-configured" },
68 { SS_INSTALLED, "installed" },
69 { SS_HALF_INSTALLED, "half-installed" },
70 { SS_CONFIG_FILES, "config-files" },
71 { SS_POST_INST_FAILED, "post-inst-failed" },
72 { SS_REMOVAL_FAILED, "removal-failed" }
75 static int verrevcmp(const char *val, const char *ref);
87 pkg->architecture = NULL;
88 pkg->maintainer = NULL;
90 pkg->description = NULL;
91 pkg->state_want = SW_UNKNOWN;
92 pkg->state_flag = SF_OK;
93 pkg->state_status = SS_NOT_INSTALLED;
94 pkg->depends_str = NULL;
95 pkg->provides_str = NULL;
96 pkg->depends_count = 0;
98 pkg->suggests_str = NULL;
99 pkg->recommends_str = NULL;
100 pkg->suggests_count = 0;
101 pkg->recommends_count = 0;
103 active_list_init(&pkg->list);
105 /* Abhaya: added init for conflicts fields */
106 pkg->conflicts = NULL;
107 pkg->conflicts_count = 0;
109 /* added for replaces. Jamey 7/23/2002 */
110 pkg->replaces = NULL;
111 pkg->replaces_count = 0;
113 pkg->pre_depends_count = 0;
114 pkg->pre_depends_str = NULL;
115 pkg->provides_count = 0;
116 pkg->provides = NULL;
117 pkg->filename = NULL;
118 pkg->local_filename = NULL;
119 pkg->tmp_unpack_dir = NULL;
121 #if defined HAVE_SHA256
122 pkg->sha256sum = NULL;
125 pkg->installed_size = NULL;
126 pkg->priority = NULL;
128 conffile_list_init(&pkg->conffiles);
129 pkg->installed_files = NULL;
130 pkg->installed_files_ref_cnt = 0;
132 pkg->provided_by_hand = 0;
139 pkg = xcalloc(1, sizeof(pkg_t));
145 void compound_depend_deinit (compound_depend_t *depends)
148 for (i = 0; i < depends->possibility_count; i++)
151 d = depends->possibilities[i];
155 free (depends->possibilities);
158 void 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
337 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
339 if (oldpkg == newpkg) {
343 if (!oldpkg->auto_installed)
344 oldpkg->auto_installed = newpkg->auto_installed;
347 oldpkg->src = newpkg->src;
349 oldpkg->dest = newpkg->dest;
350 if (!oldpkg->architecture)
351 oldpkg->architecture = xstrdup(newpkg->architecture);
352 if (!oldpkg->arch_priority)
353 oldpkg->arch_priority = newpkg->arch_priority;
354 if (!oldpkg->section)
355 oldpkg->section = xstrdup(newpkg->section);
356 if(!oldpkg->maintainer)
357 oldpkg->maintainer = xstrdup(newpkg->maintainer);
358 if(!oldpkg->description)
359 oldpkg->description = xstrdup(newpkg->description);
361 /* merge the state_flags from the new package */
362 oldpkg->state_want = newpkg->state_want;
363 oldpkg->state_status = newpkg->state_status;
364 oldpkg->state_flag = newpkg->state_flag;
366 if (oldpkg->state_want == SW_UNKNOWN)
367 oldpkg->state_want = newpkg->state_want;
368 if (oldpkg->state_status == SS_NOT_INSTALLED)
369 oldpkg->state_status = newpkg->state_status;
370 oldpkg->state_flag |= newpkg->state_flag;
373 if (!oldpkg->depends_count && !oldpkg->pre_depends_count && !oldpkg->recommends_count && !oldpkg->suggests_count) {
374 oldpkg->depends_count = newpkg->depends_count;
375 newpkg->depends_count = 0;
377 oldpkg->depends = newpkg->depends;
378 newpkg->depends = NULL;
380 oldpkg->pre_depends_count = newpkg->pre_depends_count;
381 newpkg->pre_depends_count = 0;
383 oldpkg->recommends_count = newpkg->recommends_count;
384 newpkg->recommends_count = 0;
386 oldpkg->suggests_count = newpkg->suggests_count;
387 newpkg->suggests_count = 0;
390 if (oldpkg->provides_count <= 1) {
391 oldpkg->provides_count = newpkg->provides_count;
392 newpkg->provides_count = 0;
394 if (!oldpkg->provides) {
395 oldpkg->provides = newpkg->provides;
396 newpkg->provides = NULL;
400 if (!oldpkg->conflicts_count) {
401 oldpkg->conflicts_count = newpkg->conflicts_count;
402 newpkg->conflicts_count = 0;
404 oldpkg->conflicts = newpkg->conflicts;
405 newpkg->conflicts = NULL;
408 if (!oldpkg->replaces_count) {
409 oldpkg->replaces_count = newpkg->replaces_count;
410 newpkg->replaces_count = 0;
412 oldpkg->replaces = newpkg->replaces;
413 newpkg->replaces = NULL;
416 if (!oldpkg->filename)
417 oldpkg->filename = xstrdup(newpkg->filename);
418 if (!oldpkg->local_filename)
419 oldpkg->local_filename = xstrdup(newpkg->local_filename);
420 if (!oldpkg->tmp_unpack_dir)
421 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
423 oldpkg->md5sum = xstrdup(newpkg->md5sum);
424 #if defined HAVE_SHA256
425 if (!oldpkg->sha256sum)
426 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
429 oldpkg->size = xstrdup(newpkg->size);
430 if (!oldpkg->installed_size)
431 oldpkg->installed_size = xstrdup(newpkg->installed_size);
432 if (!oldpkg->priority)
433 oldpkg->priority = xstrdup(newpkg->priority);
435 oldpkg->source = xstrdup(newpkg->source);
436 if (nv_pair_list_empty(&oldpkg->conffiles)){
437 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
438 conffile_list_init(&newpkg->conffiles);
440 if (!oldpkg->installed_files){
441 oldpkg->installed_files = newpkg->installed_files;
442 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
443 newpkg->installed_files = NULL;
445 if (!oldpkg->essential)
446 oldpkg->essential = newpkg->essential;
452 abstract_pkg_init(abstract_pkg_t *ab_pkg)
454 ab_pkg->provided_by = abstract_pkg_vec_alloc();
455 ab_pkg->dependencies_checked = 0;
456 ab_pkg->state_status = SS_NOT_INSTALLED;
459 abstract_pkg_t *abstract_pkg_new(void)
461 abstract_pkg_t * ab_pkg;
463 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
464 abstract_pkg_init(ab_pkg);
469 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
473 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
475 fp = fopen(file_name, "r");
477 opkg_message(conf, OPKG_ERROR, "fopen(%s): %s\n",
478 file_name, strerror(errno));
485 if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
486 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
494 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
498 int depends_count = pkg->pre_depends_count +
500 pkg->recommends_count +
503 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
504 goto UNKNOWN_FMT_FIELD;
511 if (strcasecmp(field, "Architecture") == 0) {
512 if (pkg->architecture) {
513 fprintf(fp, "Architecture: %s\n", pkg->architecture);
515 } else if (strcasecmp(field, "Auto-Installed") == 0) {
516 if (pkg->auto_installed)
517 fprintf(fp, "Auto-Installed: yes\n");
519 goto UNKNOWN_FMT_FIELD;
524 if (strcasecmp(field, "Conffiles") == 0) {
525 conffile_list_elt_t *iter;
527 if (nv_pair_list_empty(&pkg->conffiles))
530 fprintf(fp, "Conffiles:\n");
531 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
532 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
533 fprintf(fp, " %s %s\n",
534 ((conffile_t *)iter->data)->name,
535 ((conffile_t *)iter->data)->value);
538 } else if (strcasecmp(field, "Conflicts") == 0) {
540 if (pkg->conflicts_count) {
541 fprintf(fp, "Conflicts:");
542 for(i = 0; i < pkg->conflicts_count; i++) {
543 cdep = pkg->conflicts[i].possibilities[0];
544 fprintf(fp, "%s %s", i == 0 ? "" : ",",
547 fprintf(fp, " (%s%s)",
548 constraint_to_str(cdep->constraint),
555 goto UNKNOWN_FMT_FIELD;
560 if (strcasecmp(field, "Depends") == 0) {
561 if (pkg->depends_count) {
562 fprintf(fp, "Depends:");
563 for (j=0, i=0; i<depends_count; i++) {
564 if (pkg->depends[i].type != DEPEND)
566 str = pkg_depend_str(pkg, i);
567 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
573 } else if (strcasecmp(field, "Description") == 0) {
574 if (pkg->description) {
575 fprintf(fp, "Description: %s\n", pkg->description);
578 goto UNKNOWN_FMT_FIELD;
583 if (pkg->essential) {
584 fprintf(fp, "Essential: yes\n");
590 fprintf(fp, "Filename: %s\n", pkg->filename);
595 if (strcasecmp(field, "Installed-Size") == 0) {
596 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
597 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
598 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
603 if (strcasecmp(field, "Maintainer") == 0) {
604 if (pkg->maintainer) {
605 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
607 } else if (strcasecmp(field, "MD5sum") == 0) {
609 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
612 goto UNKNOWN_FMT_FIELD;
617 if (strcasecmp(field, "Package") == 0) {
618 fprintf(fp, "Package: %s\n", pkg->name);
619 } else if (strcasecmp(field, "Priority") == 0) {
620 fprintf(fp, "Priority: %s\n", pkg->priority);
621 } else if (strcasecmp(field, "Provides") == 0) {
622 if (pkg->provides_count) {
623 fprintf(fp, "Provides:");
624 for(i = 1; i < pkg->provides_count; i++) {
625 fprintf(fp, "%s %s", i == 1 ? "" : ",",
626 pkg->provides[i]->name);
631 goto UNKNOWN_FMT_FIELD;
636 if (strcasecmp (field, "Replaces") == 0) {
637 if (pkg->replaces_count) {
638 fprintf(fp, "Replaces:");
639 for (i = 0; i < pkg->replaces_count; i++) {
640 fprintf(fp, "%s %s", i == 0 ? "" : ",",
641 pkg->replaces[i]->name);
645 } else if (strcasecmp (field, "Recommends") == 0) {
646 if (pkg->recommends_count) {
647 fprintf(fp, "Recommends:");
648 for (j=0, i=0; i<depends_count; i++) {
649 if (pkg->depends[i].type != RECOMMEND)
651 str = pkg_depend_str(pkg, i);
652 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
659 goto UNKNOWN_FMT_FIELD;
664 if (strcasecmp(field, "Section") == 0) {
666 fprintf(fp, "Section: %s\n", pkg->section);
668 #if defined HAVE_SHA256
669 } else if (strcasecmp(field, "SHA256sum") == 0) {
670 if (pkg->sha256sum) {
671 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
674 } else if (strcasecmp(field, "Size") == 0) {
676 fprintf(fp, "Size: %s\n", pkg->size);
678 } else if (strcasecmp(field, "Source") == 0) {
680 fprintf(fp, "Source: %s\n", pkg->source);
682 } else if (strcasecmp(field, "Status") == 0) {
683 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
684 char *pstat = pkg_state_status_to_str(pkg->state_status);
685 char *pwant = pkg_state_want_to_str(pkg->state_want);
687 if (pflag == NULL || pstat == NULL || pwant == NULL)
690 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
695 } else if (strcasecmp(field, "Suggests") == 0) {
696 if (pkg->suggests_count) {
697 fprintf(fp, "Suggests:");
698 for (j=0, i=0; i<depends_count; i++) {
699 if (pkg->depends[i].type != SUGGEST)
701 str = pkg_depend_str(pkg, i);
702 fprintf(fp, "%s %s", j == 0 ? "" : ",", str);
709 goto UNKNOWN_FMT_FIELD;
714 if (strcasecmp(field, "Tags") == 0) {
716 fprintf(fp, "Tags: %s\n", pkg->tags);
723 char *version = pkg_version_str_alloc(pkg);
726 fprintf(fp, "Version: %s\n", version);
731 goto UNKNOWN_FMT_FIELD;
737 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
740 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
742 pkg_formatted_field(fp, pkg, "Package");
743 pkg_formatted_field(fp, pkg, "Version");
744 pkg_formatted_field(fp, pkg, "Depends");
745 pkg_formatted_field(fp, pkg, "Recommends");
746 pkg_formatted_field(fp, pkg, "Suggests");
747 pkg_formatted_field(fp, pkg, "Provides");
748 pkg_formatted_field(fp, pkg, "Replaces");
749 pkg_formatted_field(fp, pkg, "Conflicts");
750 pkg_formatted_field(fp, pkg, "Status");
751 pkg_formatted_field(fp, pkg, "Section");
752 pkg_formatted_field(fp, pkg, "Essential");
753 pkg_formatted_field(fp, pkg, "Architecture");
754 pkg_formatted_field(fp, pkg, "Maintainer");
755 pkg_formatted_field(fp, pkg, "MD5sum");
756 pkg_formatted_field(fp, pkg, "Size");
757 pkg_formatted_field(fp, pkg, "Filename");
758 pkg_formatted_field(fp, pkg, "Conffiles");
759 pkg_formatted_field(fp, pkg, "Source");
760 pkg_formatted_field(fp, pkg, "Description");
761 pkg_formatted_field(fp, pkg, "Installed-Time");
762 pkg_formatted_field(fp, pkg, "Tags");
766 void pkg_print_status(pkg_t * pkg, FILE * file)
772 /* XXX: QUESTION: Do we actually want more fields here? The
773 original idea was to save space by installing only what was
774 needed for actual computation, (package, version, status,
775 essential, conffiles). The assumption is that all other fields
776 can be found in th available file.
778 But, someone proposed the idea to make it possible to
779 reconstruct a .opk from an installed package, (ie. for beaming
780 from one handheld to another). So, maybe we actually want a few
781 more fields here, (depends, suggests, etc.), so that that would
782 be guaranteed to work even in the absence of more information
783 from the available file.
785 28-MAR-03: kergoth and I discussed this yesterday. We think
786 the essential info needs to be here for all installed packages
787 because they may not appear in the Packages files on various
788 feeds. Furthermore, one should be able to install from URL or
789 local storage without requiring a Packages file from any feed.
792 pkg_formatted_field(file, pkg, "Package");
793 pkg_formatted_field(file, pkg, "Version");
794 pkg_formatted_field(file, pkg, "Depends");
795 pkg_formatted_field(file, pkg, "Recommends");
796 pkg_formatted_field(file, pkg, "Suggests");
797 pkg_formatted_field(file, pkg, "Provides");
798 pkg_formatted_field(file, pkg, "Replaces");
799 pkg_formatted_field(file, pkg, "Conflicts");
800 pkg_formatted_field(file, pkg, "Status");
801 pkg_formatted_field(file, pkg, "Essential");
802 pkg_formatted_field(file, pkg, "Architecture");
803 pkg_formatted_field(file, pkg, "Conffiles");
804 pkg_formatted_field(file, pkg, "Installed-Time");
805 pkg_formatted_field(file, pkg, "Auto-Installed");
810 * libdpkg - Debian packaging suite library routines
811 * vercmp.c - comparison of version numbers
813 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
815 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
819 if (pkg->epoch > ref_pkg->epoch) {
823 if (pkg->epoch < ref_pkg->epoch) {
827 r = verrevcmp(pkg->version, ref_pkg->version);
832 r = verrevcmp(pkg->revision, ref_pkg->revision);
840 /* assume ascii; warning: evaluates x multiple times! */
841 #define order(x) ((x) == '~' ? -1 \
844 : isalpha((x)) ? (x) \
847 static int verrevcmp(const char *val, const char *ref) {
851 while (*val || *ref) {
854 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
855 int vc= order(*val), rc= order(*ref);
856 if (vc != rc) return vc - rc;
860 while ( *val == '0' ) val++;
861 while ( *ref == '0' ) ref++;
862 while (isdigit(*val) && isdigit(*ref)) {
863 if (!first_diff) first_diff= *val - *ref;
866 if (isdigit(*val)) return 1;
867 if (isdigit(*ref)) return -1;
868 if (first_diff) return first_diff;
873 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
877 r = pkg_compare_versions(it, ref);
879 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
883 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
887 if (strcmp(op, "<<") == 0) {
891 if (strcmp(op, ">>") == 0) {
895 if (strcmp(op, "=") == 0) {
899 fprintf(stderr, "unknown operator: %s", op);
903 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
905 const pkg_t *a = *(const pkg_t**) p1;
906 const pkg_t *b = *(const pkg_t**) p2;
909 if (!a->name || !b->name) {
910 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
911 a, a->name, b, b->name);
915 namecmp = strcmp(a->name, b->name);
918 vercmp = pkg_compare_versions(a, b);
921 if (!a->arch_priority || !b->arch_priority) {
922 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
923 a, a->arch_priority, b, b->arch_priority);
926 if (a->arch_priority > b->arch_priority)
928 if (a->arch_priority < b->arch_priority)
933 int abstract_pkg_name_compare(const void *p1, const void *p2)
935 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
936 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
937 if (!a->name || !b->name) {
938 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
939 a, a->name, b, b->name);
942 return strcmp(a->name, b->name);
947 pkg_version_str_alloc(pkg_t *pkg)
953 sprintf_alloc(&version, "%d:%s-%s",
954 pkg->epoch, pkg->version, pkg->revision);
956 sprintf_alloc(&version, "%d:%s",
957 pkg->epoch, pkg->version);
960 sprintf_alloc(&version, "%s-%s",
961 pkg->version, pkg->revision);
963 version = xstrdup(pkg->version);
970 * XXX: this should be broken into two functions
972 str_list_t *pkg_get_installed_files(opkg_conf_t *conf, pkg_t *pkg)
975 char *list_file_name = NULL;
976 FILE *list_file = NULL;
978 char *installed_file_name;
981 pkg->installed_files_ref_cnt++;
983 if (pkg->installed_files) {
984 return pkg->installed_files;
987 pkg->installed_files = str_list_alloc();
989 /* For uninstalled packages, get the file list directly from the package.
990 For installed packages, look at the package.list file in the database.
992 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
993 if (pkg->local_filename == NULL) {
994 return pkg->installed_files;
996 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
997 file. In other words, change deb_extract so that it can
998 simply return the file list as a char *[] rather than
999 insisting on writing in to a FILE * as it does now. */
1000 sprintf_alloc(&list_file_name, "%s/%s.list.XXXXXX",
1001 conf->tmp_dir, pkg->name);
1002 fd = mkstemp(list_file_name);
1004 opkg_message(conf, OPKG_ERROR, "%s: mkstemp(%s): %s",
1005 __FUNCTION__, list_file_name, strerror(errno));
1006 free(list_file_name);
1007 return pkg->installed_files;
1009 list_file = fdopen(fd, "r+");
1010 if (list_file == NULL) {
1011 opkg_message(conf, OPKG_ERROR, "%s: fdopen: %s",
1012 __FUNCTION__, strerror(errno));
1014 unlink(list_file_name);
1015 free(list_file_name);
1016 return pkg->installed_files;
1018 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1020 opkg_message(conf, OPKG_ERROR, "%s: Error extracting file list "
1021 "from %s: %s\n", __FUNCTION__,
1022 pkg->local_filename, strerror(err));
1024 unlink(list_file_name);
1025 free(list_file_name);
1026 return pkg->installed_files;
1030 sprintf_alloc(&list_file_name, "%s/%s.list",
1031 pkg->dest->info_dir, pkg->name);
1032 list_file = fopen(list_file_name, "r");
1033 if (list_file == NULL) {
1034 opkg_message(conf, OPKG_ERROR, "%s: fopen(%s): %s\n",
1035 __FUNCTION__, list_file_name, strerror(errno));
1036 free(list_file_name);
1037 return pkg->installed_files;
1039 free(list_file_name);
1042 if (conf->offline_root)
1043 rootdirlen = strlen(conf->offline_root);
1048 line = file_read_line_alloc(list_file);
1055 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1056 if (*file_name == '.') {
1059 if (*file_name == '/') {
1062 sprintf_alloc(&installed_file_name, "%s%s",
1063 pkg->dest->root_dir, file_name);
1065 if (conf->offline_root &&
1066 strncmp(conf->offline_root, file_name, rootdirlen)) {
1067 sprintf_alloc(&installed_file_name, "%s%s",
1068 conf->offline_root, file_name);
1070 // already contains root_dir as header -> ABSOLUTE
1071 sprintf_alloc(&installed_file_name, "%s", file_name);
1074 str_list_append(pkg->installed_files, installed_file_name);
1075 free(installed_file_name);
1081 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1082 unlink(list_file_name);
1083 free(list_file_name);
1086 return pkg->installed_files;
1089 /* XXX: CLEANUP: This function and it's counterpart,
1090 (pkg_get_installed_files), do not match our init/deinit naming
1091 convention. Nor the alloc/free convention. But, then again, neither
1092 of these conventions currrently fit the way these two functions
1094 int pkg_free_installed_files(pkg_t *pkg)
1096 pkg->installed_files_ref_cnt--;
1098 if (pkg->installed_files_ref_cnt > 0)
1101 if (pkg->installed_files) {
1102 str_list_purge(pkg->installed_files);
1105 pkg->installed_files = NULL;
1110 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1113 char *list_file_name;
1115 //I don't think pkg_free_installed_files should be called here. Jamey
1116 //pkg_free_installed_files(pkg);
1118 sprintf_alloc(&list_file_name, "%s/%s.list",
1119 pkg->dest->info_dir, pkg->name);
1120 if (!conf->noaction) {
1121 err = unlink(list_file_name);
1122 free(list_file_name);
1131 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1133 conffile_list_elt_t *iter;
1134 conffile_t *conffile;
1140 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1141 conffile = (conffile_t *)iter->data;
1143 if (strcmp(conffile->name, file_name) == 0) {
1151 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1152 const char *script, const char *args)
1161 /* XXX: CLEANUP: There must be a better way to handle maintainer
1162 scripts when running with offline_root mode and/or a dest other
1163 than '/'. I've been playing around with some clever chroot
1164 tricks and I might come up with something workable. */
1166 * Attempt to provide a restricted environment for offline operation
1167 * Need the following set as a minimum:
1168 * OPKG_OFFLINE_ROOT = absolute path to root dir
1169 * D = absolute path to root dir (for OE generated postinst)
1170 * PATH = something safe (a restricted set of utilities)
1173 if (conf->offline_root) {
1174 if (conf->offline_root_path) {
1175 setenv("PATH", conf->offline_root_path, 1);
1177 opkg_message(conf, OPKG_NOTICE,
1178 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1181 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1182 setenv("D", conf->offline_root, 1);
1185 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1186 maintainer script within a chroot environment. */
1188 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1189 have scripts in pkg->tmp_unpack_dir. */
1190 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1191 if (pkg->dest == NULL) {
1192 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1193 __FUNCTION__, pkg->name);
1196 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1198 if (pkg->tmp_unpack_dir == NULL) {
1199 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1200 __FUNCTION__, pkg->name);
1203 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1206 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1209 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1211 if (! file_exists(path)) {
1216 sprintf_alloc(&cmd, "%s %s", path, args);
1219 const char *argv[] = {"sh", "-c", cmd, NULL};
1220 err = xsystem(argv);
1225 fprintf(stderr, "%s script returned status %d\n", script, err);
1232 char *pkg_state_want_to_str(pkg_state_want_t sw)
1236 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1237 if (pkg_state_want_map[i].value == sw) {
1238 return xstrdup(pkg_state_want_map[i].str);
1242 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1244 return xstrdup("<STATE_WANT_UNKNOWN>");
1247 pkg_state_want_t pkg_state_want_from_str(char *str)
1251 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1252 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1253 return pkg_state_want_map[i].value;
1257 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1262 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1265 int len = 3; /* ok\000 is minimum */
1268 /* clear the temporary flags before converting to string */
1269 sf &= SF_NONVOLATILE_FLAGS;
1272 return xstrdup("ok");
1275 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1276 if (sf & pkg_state_flag_map[i].value) {
1277 len += strlen(pkg_state_flag_map[i].str) + 1;
1282 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1283 if (sf & pkg_state_flag_map[i].value) {
1284 strcat(str, pkg_state_flag_map[i].str);
1289 str[len-1] = 0; /* squash last comma */
1294 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1299 if (strcmp(str, "ok") == 0) {
1302 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1303 const char *sfname = pkg_state_flag_map[i].str;
1304 int sfname_len = strlen(sfname);
1305 if (strncmp(str, sfname, sfname_len) == 0) {
1306 sf |= pkg_state_flag_map[i].value;
1308 if (str[0] == ',') {
1319 char *pkg_state_status_to_str(pkg_state_status_t ss)
1323 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1324 if (pkg_state_status_map[i].value == ss) {
1325 return xstrdup(pkg_state_status_map[i].str);
1329 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1331 return xstrdup("<STATE_STATUS_UNKNOWN>");
1334 pkg_state_status_t pkg_state_status_from_str(const char *str)
1338 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1339 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1340 return pkg_state_status_map[i].value;
1344 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1346 return SS_NOT_INSTALLED;
1349 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1351 nv_pair_list_elt_t *l;
1353 if (!pkg->architecture)
1356 list_for_each_entry(l , &conf->arch_list.head, node) {
1357 nv_pair_t *nv = (nv_pair_t *)l->data;
1358 if (strcmp(nv->name, pkg->architecture) == 0) {
1359 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1364 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1368 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1370 nv_pair_list_elt_t *l;
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, archname) == 0) {
1375 int priority = strtol(nv->value, NULL, 0);
1382 int pkg_info_preinstall_check(opkg_conf_t *conf)
1385 hash_table_t *pkg_hash = &conf->pkg_hash;
1386 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1387 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1389 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1390 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1391 /* update arch_priority for each package */
1392 for (i = 0; i < available_pkgs->len; i++) {
1393 pkg_t *pkg = available_pkgs->pkgs[i];
1394 int arch_priority = 1;
1397 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1398 if (pkg->architecture)
1399 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1401 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1402 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1403 pkg->arch_priority = arch_priority;
1406 for (i = 0; i < available_pkgs->len; i++) {
1407 pkg_t *pkg = available_pkgs->pkgs[i];
1408 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1409 /* clear flags and want for any uninstallable package */
1410 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1411 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1412 pkg->state_want = SW_UNKNOWN;
1413 pkg->state_flag = 0;
1416 pkg_vec_free(available_pkgs);
1418 /* update the file owner data structure */
1419 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1420 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1421 for (i = 0; i < installed_pkgs->len; i++) {
1422 pkg_t *pkg = installed_pkgs->pkgs[i];
1423 str_list_t *installed_files = pkg_get_installed_files(conf, pkg); /* this causes installed_files to be cached */
1424 str_list_elt_t *iter, *niter;
1425 if (installed_files == NULL) {
1426 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1429 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1431 iter = niter, niter = str_list_next(installed_files, iter)) {
1432 char *installed_file = (char *) iter->data;
1433 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1434 file_hash_set_file_owner(conf, installed_file, pkg);
1436 pkg_free_installed_files(pkg);
1438 pkg_vec_free(installed_pkgs);
1443 struct pkg_write_filelist_data {
1449 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1451 struct pkg_write_filelist_data *data = data_;
1452 pkg_t *entry = entry_;
1453 if (entry == data->pkg) {
1454 fprintf(data->stream, "%s\n", key);
1458 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1460 struct pkg_write_filelist_data data;
1461 char *list_file_name = NULL;
1465 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1468 opkg_message(conf, OPKG_INFO,
1469 " creating %s.list file\n", pkg->name);
1470 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1471 if (!list_file_name) {
1472 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1475 opkg_message(conf, OPKG_INFO,
1476 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1477 data.stream = fopen(list_file_name, "w");
1479 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1480 list_file_name, strerror(errno));
1485 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1486 fclose(data.stream);
1487 free(list_file_name);
1489 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1494 int pkg_write_changed_filelists(opkg_conf_t *conf)
1496 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1497 hash_table_t *pkg_hash = &conf->pkg_hash;
1503 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1504 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1505 for (i = 0; i < installed_pkgs->len; i++) {
1506 pkg_t *pkg = installed_pkgs->pkgs[i];
1507 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1508 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1509 err = pkg_write_filelist(conf, pkg);
1511 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1514 pkg_vec_free (installed_pkgs);