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);
82 pkg = xcalloc(1, sizeof(pkg_t));
88 int pkg_init(pkg_t *pkg)
96 pkg->architecture = NULL;
97 pkg->maintainer = NULL;
99 pkg->description = NULL;
100 pkg->state_want = SW_UNKNOWN;
101 pkg->state_flag = SF_OK;
102 pkg->state_status = SS_NOT_INSTALLED;
103 pkg->depends_str = NULL;
104 pkg->provides_str = NULL;
105 pkg->depends_count = 0;
107 pkg->suggests_str = NULL;
108 pkg->recommends_str = NULL;
109 pkg->suggests_count = 0;
110 pkg->recommends_count = 0;
112 active_list_init(&pkg->list);
114 /* Abhaya: added init for conflicts fields */
115 pkg->conflicts = NULL;
116 pkg->conflicts_count = 0;
118 /* added for replaces. Jamey 7/23/2002 */
119 pkg->replaces = NULL;
120 pkg->replaces_count = 0;
122 pkg->pre_depends_count = 0;
123 pkg->pre_depends_str = NULL;
124 pkg->provides_count = 0;
125 pkg->provides = NULL;
126 pkg->filename = NULL;
127 pkg->local_filename = NULL;
128 pkg->tmp_unpack_dir = NULL;
130 #if defined HAVE_SHA256
131 pkg->sha256sum = NULL;
134 pkg->installed_size = NULL;
135 pkg->priority = NULL;
137 conffile_list_init(&pkg->conffiles);
138 pkg->installed_files = NULL;
139 pkg->installed_files_ref_cnt = 0;
141 pkg->provided_by_hand = 0;
146 void compound_depend_deinit (compound_depend_t *depends)
149 for (i = 0; i < depends->possibility_count; i++)
152 d = depends->possibilities[i];
156 free (depends->possibilities);
159 void pkg_deinit(pkg_t *pkg)
172 /* revision shares storage with version, so don't free */
173 pkg->revision = NULL;
175 /* owned by opkg_conf_t */
177 /* owned by opkg_conf_t */
180 if (pkg->architecture)
181 free(pkg->architecture);
182 pkg->architecture = NULL;
185 free(pkg->maintainer);
186 pkg->maintainer = NULL;
192 if (pkg->description)
193 free(pkg->description);
194 pkg->description = NULL;
196 pkg->state_want = SW_UNKNOWN;
197 pkg->state_flag = SF_OK;
198 pkg->state_status = SS_NOT_INSTALLED;
200 active_list_clear(&pkg->list);
203 free (pkg->replaces);
204 pkg->replaces = NULL;
206 for (i = 0; i < pkg->depends_count; i++)
207 free (pkg->depends_str[i]);
208 free(pkg->depends_str);
209 pkg->depends_str = NULL;
211 for (i = 0; i < pkg->provides_count-1; i++)
212 free (pkg->provides_str[i]);
213 free(pkg->provides_str);
214 pkg->provides_str = NULL;
216 for (i = 0; i < pkg->conflicts_count; i++)
217 free (pkg->conflicts_str[i]);
218 free(pkg->conflicts_str);
219 pkg->conflicts_str = NULL;
221 for (i = 0; i < pkg->replaces_count; i++)
222 free (pkg->replaces_str[i]);
223 free(pkg->replaces_str);
224 pkg->replaces_str = NULL;
226 for (i = 0; i < pkg->recommends_count; i++)
227 free (pkg->recommends_str[i]);
228 free(pkg->recommends_str);
229 pkg->recommends_str = NULL;
231 for (i = 0; i < pkg->suggests_count; i++)
232 free (pkg->suggests_str[i]);
233 free(pkg->suggests_str);
234 pkg->suggests_str = NULL;
237 int count = pkg->pre_depends_count
239 + pkg->recommends_count
240 + pkg->suggests_count;
242 for (i=0; i<count; i++)
243 compound_depend_deinit (&pkg->depends[i]);
247 if (pkg->conflicts) {
248 for (i=0; i<pkg->conflicts_count; i++)
249 compound_depend_deinit (&pkg->conflicts[i]);
250 free (pkg->conflicts);
254 free (pkg->provides);
256 pkg->pre_depends_count = 0;
257 if (pkg->pre_depends_str)
258 free(pkg->pre_depends_str);
259 pkg->pre_depends_str = NULL;
261 pkg->provides_count = 0;
265 pkg->filename = NULL;
267 if (pkg->local_filename)
268 free(pkg->local_filename);
269 pkg->local_filename = NULL;
271 /* CLEANUP: It'd be nice to pullin the cleanup function from
272 opkg_install.c here. See comment in
273 opkg_install.c:cleanup_temporary_files */
274 if (pkg->tmp_unpack_dir)
275 free(pkg->tmp_unpack_dir);
276 pkg->tmp_unpack_dir = NULL;
282 #if defined HAVE_SHA256
284 free(pkg->sha256sum);
285 pkg->sha256sum = NULL;
292 if (pkg->installed_size)
293 free(pkg->installed_size);
294 pkg->installed_size = NULL;
298 pkg->priority = NULL;
304 conffile_list_deinit(&pkg->conffiles);
306 /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
307 since if they are calling deinit, they should know. Maybe do an
308 assertion here instead? */
309 pkg->installed_files_ref_cnt = 1;
310 pkg_free_installed_files(pkg);
318 int pkg_init_from_file(pkg_t *pkg, const char *filename)
324 if (err) { return err; }
326 pkg->local_filename = xstrdup(filename);
328 control_file = tmpfile();
329 err = pkg_extract_control_file_to_stream(pkg, control_file);
330 if (err) { return err; }
332 rewind(control_file);
333 pkg_parse_from_stream(pkg, control_file, PFM_ALL);
335 fclose(control_file);
340 /* Merge any new information in newpkg into oldpkg */
341 /* XXX: CLEANUP: This function shouldn't actually modify anything in
342 newpkg, but should leave it usable. This rework is so that
343 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
345 * uh, i thought that i had originally written this so that it took
346 * two pkgs and returned a new one? we can do that again... -sma
348 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
350 if (oldpkg == newpkg) {
355 oldpkg->src = newpkg->src;
357 oldpkg->dest = newpkg->dest;
358 if (!oldpkg->architecture)
359 oldpkg->architecture = xstrdup(newpkg->architecture);
360 if (!oldpkg->arch_priority)
361 oldpkg->arch_priority = newpkg->arch_priority;
362 if (!oldpkg->section)
363 oldpkg->section = xstrdup(newpkg->section);
364 if(!oldpkg->maintainer)
365 oldpkg->maintainer = xstrdup(newpkg->maintainer);
366 if(!oldpkg->description)
367 oldpkg->description = xstrdup(newpkg->description);
369 /* merge the state_flags from the new package */
370 oldpkg->state_want = newpkg->state_want;
371 oldpkg->state_status = newpkg->state_status;
372 oldpkg->state_flag = newpkg->state_flag;
374 if (oldpkg->state_want == SW_UNKNOWN)
375 oldpkg->state_want = newpkg->state_want;
376 if (oldpkg->state_status == SS_NOT_INSTALLED)
377 oldpkg->state_status = newpkg->state_status;
378 oldpkg->state_flag |= newpkg->state_flag;
381 if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
382 oldpkg->depends_str = newpkg->depends_str;
383 newpkg->depends_str = NULL;
384 oldpkg->depends_count = newpkg->depends_count;
385 newpkg->depends_count = 0;
387 oldpkg->depends = newpkg->depends;
388 newpkg->depends = NULL;
390 oldpkg->pre_depends_str = newpkg->pre_depends_str;
391 newpkg->pre_depends_str = NULL;
392 oldpkg->pre_depends_count = newpkg->pre_depends_count;
393 newpkg->pre_depends_count = 0;
395 oldpkg->recommends_str = newpkg->recommends_str;
396 newpkg->recommends_str = NULL;
397 oldpkg->recommends_count = newpkg->recommends_count;
398 newpkg->recommends_count = 0;
400 oldpkg->suggests_str = newpkg->suggests_str;
401 newpkg->suggests_str = NULL;
402 oldpkg->suggests_count = newpkg->suggests_count;
403 newpkg->suggests_count = 0;
406 if (!oldpkg->provides_str) {
407 oldpkg->provides_str = newpkg->provides_str;
408 newpkg->provides_str = NULL;
409 oldpkg->provides_count = newpkg->provides_count;
410 newpkg->provides_count = 0;
412 if (!oldpkg->provides) {
413 oldpkg->provides = newpkg->provides;
414 newpkg->provides = NULL;
418 if (!oldpkg->conflicts_str) {
419 oldpkg->conflicts_str = newpkg->conflicts_str;
420 newpkg->conflicts_str = NULL;
421 oldpkg->conflicts_count = newpkg->conflicts_count;
422 newpkg->conflicts_count = 0;
424 oldpkg->conflicts = newpkg->conflicts;
425 newpkg->conflicts = NULL;
428 if (!oldpkg->replaces_str) {
429 oldpkg->replaces_str = newpkg->replaces_str;
430 newpkg->replaces_str = NULL;
431 oldpkg->replaces_count = newpkg->replaces_count;
432 newpkg->replaces_count = 0;
434 oldpkg->replaces = newpkg->replaces;
435 newpkg->replaces = NULL;
438 if (!oldpkg->filename)
439 oldpkg->filename = xstrdup(newpkg->filename);
440 if (!oldpkg->local_filename)
441 oldpkg->local_filename = xstrdup(newpkg->local_filename);
442 if (!oldpkg->tmp_unpack_dir)
443 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
445 oldpkg->md5sum = xstrdup(newpkg->md5sum);
446 #if defined HAVE_SHA256
447 if (!oldpkg->sha256sum)
448 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
451 oldpkg->size = xstrdup(newpkg->size);
452 if (!oldpkg->installed_size)
453 oldpkg->installed_size = xstrdup(newpkg->installed_size);
454 if (!oldpkg->priority)
455 oldpkg->priority = xstrdup(newpkg->priority);
457 oldpkg->source = xstrdup(newpkg->source);
458 if (nv_pair_list_empty(&oldpkg->conffiles)){
459 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
460 conffile_list_init(&newpkg->conffiles);
462 if (!oldpkg->installed_files){
463 oldpkg->installed_files = newpkg->installed_files;
464 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
465 newpkg->installed_files = NULL;
467 if (!oldpkg->essential)
468 oldpkg->essential = newpkg->essential;
473 abstract_pkg_t *abstract_pkg_new(void)
475 abstract_pkg_t * ab_pkg;
477 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
479 if (ab_pkg == NULL) {
480 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
484 if ( abstract_pkg_init(ab_pkg) < 0 )
490 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
492 ab_pkg->provided_by = abstract_pkg_vec_alloc();
493 if (ab_pkg->provided_by==NULL){
496 ab_pkg->dependencies_checked = 0;
497 ab_pkg->state_status = SS_NOT_INSTALLED;
502 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
506 sprintf_alloc(&file_name,"%s/%s.control", pkg->dest->info_dir, pkg->name);
508 fp = fopen(file_name, "r");
510 opkg_message(conf, OPKG_ERROR, "fopen(%s): %s\n",
511 file_name, strerror(errno));
518 if (pkg_parse_from_stream(pkg, fp, PFM_ESSENTIAL)) {
519 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
527 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
531 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
532 goto UNKNOWN_FMT_FIELD;
539 if (strcasecmp(field, "Architecture") == 0) {
540 if (pkg->architecture) {
541 fprintf(fp, "Architecture: %s\n", pkg->architecture);
543 } else if (strcasecmp(field, "Auto-Installed") == 0) {
544 if (pkg->auto_installed)
545 fprintf(fp, "Auto-Installed: yes\n");
547 goto UNKNOWN_FMT_FIELD;
552 if (strcasecmp(field, "Conffiles") == 0) {
553 conffile_list_elt_t *iter;
555 if (nv_pair_list_empty(&pkg->conffiles))
558 fprintf(fp, "Conffiles:\n");
559 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
560 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
561 fprintf(fp, " %s %s\n",
562 ((conffile_t *)iter->data)->name,
563 ((conffile_t *)iter->data)->value);
566 } else if (strcasecmp(field, "Conflicts") == 0) {
567 if (pkg->conflicts_count) {
568 fprintf(fp, "Conflicts:");
569 for(i = 0; i < pkg->conflicts_count; i++) {
570 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
575 goto UNKNOWN_FMT_FIELD;
580 if (strcasecmp(field, "Depends") == 0) {
581 if (pkg->depends_count) {
582 fprintf(fp, "Depends:");
583 for(i = 0; i < pkg->depends_count; i++) {
584 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
588 } else if (strcasecmp(field, "Description") == 0) {
589 if (pkg->description) {
590 fprintf(fp, "Description: %s\n", pkg->description);
593 goto UNKNOWN_FMT_FIELD;
598 if (pkg->essential) {
599 fprintf(fp, "Essential: yes\n");
605 fprintf(fp, "Filename: %s\n", pkg->filename);
610 if (strcasecmp(field, "Installed-Size") == 0) {
611 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
612 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
613 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
618 if (strcasecmp(field, "Maintainer") == 0) {
619 if (pkg->maintainer) {
620 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
622 } else if (strcasecmp(field, "MD5sum") == 0) {
624 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
627 goto UNKNOWN_FMT_FIELD;
632 if (strcasecmp(field, "Package") == 0) {
633 fprintf(fp, "Package: %s\n", pkg->name);
634 } else if (strcasecmp(field, "Priority") == 0) {
635 fprintf(fp, "Priority: %s\n", pkg->priority);
636 } else if (strcasecmp(field, "Provides") == 0) {
637 if (pkg->provides_count) {
638 fprintf(fp, "Provides:");
639 for(i = 0; i < pkg->provides_count-1; i++) {
640 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->provides_str[i]);
645 goto UNKNOWN_FMT_FIELD;
650 if (strcasecmp (field, "Replaces") == 0) {
651 if (pkg->replaces_count) {
652 fprintf(fp, "Replaces:");
653 for (i = 0; i < pkg->replaces_count; i++) {
654 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
658 } else if (strcasecmp (field, "Recommends") == 0) {
659 if (pkg->recommends_count) {
660 fprintf(fp, "Recommends:");
661 for(i = 0; i < pkg->recommends_count; i++) {
662 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
667 goto UNKNOWN_FMT_FIELD;
672 if (strcasecmp(field, "Section") == 0) {
674 fprintf(fp, "Section: %s\n", pkg->section);
676 #if defined HAVE_SHA256
677 } else if (strcasecmp(field, "SHA256sum") == 0) {
678 if (pkg->sha256sum) {
679 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
682 } else if (strcasecmp(field, "Size") == 0) {
684 fprintf(fp, "Size: %s\n", pkg->size);
686 } else if (strcasecmp(field, "Source") == 0) {
688 fprintf(fp, "Source: %s\n", pkg->source);
690 } else if (strcasecmp(field, "Status") == 0) {
691 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
692 char *pstat = pkg_state_status_to_str(pkg->state_status);
693 char *pwant = pkg_state_want_to_str(pkg->state_want);
695 if (pflag == NULL || pstat == NULL || pwant == NULL)
698 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
703 } else if (strcasecmp(field, "Suggests") == 0) {
704 if (pkg->suggests_count) {
705 fprintf(fp, "Suggests:");
706 for(i = 0; i < pkg->suggests_count; i++) {
707 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
712 goto UNKNOWN_FMT_FIELD;
717 if (strcasecmp(field, "Tags") == 0) {
719 fprintf(fp, "Tags: %s\n", pkg->tags);
726 char *version = pkg_version_str_alloc(pkg);
729 fprintf(fp, "Version: %s\n", version);
734 goto UNKNOWN_FMT_FIELD;
740 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
743 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
745 pkg_formatted_field(fp, pkg, "Package");
746 pkg_formatted_field(fp, pkg, "Version");
747 pkg_formatted_field(fp, pkg, "Depends");
748 pkg_formatted_field(fp, pkg, "Recommends");
749 pkg_formatted_field(fp, pkg, "Suggests");
750 pkg_formatted_field(fp, pkg, "Provides");
751 pkg_formatted_field(fp, pkg, "Replaces");
752 pkg_formatted_field(fp, pkg, "Conflicts");
753 pkg_formatted_field(fp, pkg, "Status");
754 pkg_formatted_field(fp, pkg, "Section");
755 pkg_formatted_field(fp, pkg, "Essential");
756 pkg_formatted_field(fp, pkg, "Architecture");
757 pkg_formatted_field(fp, pkg, "Maintainer");
758 pkg_formatted_field(fp, pkg, "MD5sum");
759 pkg_formatted_field(fp, pkg, "Size");
760 pkg_formatted_field(fp, pkg, "Filename");
761 pkg_formatted_field(fp, pkg, "Conffiles");
762 pkg_formatted_field(fp, pkg, "Source");
763 pkg_formatted_field(fp, pkg, "Description");
764 pkg_formatted_field(fp, pkg, "Installed-Time");
765 pkg_formatted_field(fp, pkg, "Tags");
769 void pkg_print_status(pkg_t * pkg, FILE * file)
775 /* XXX: QUESTION: Do we actually want more fields here? The
776 original idea was to save space by installing only what was
777 needed for actual computation, (package, version, status,
778 essential, conffiles). The assumption is that all other fields
779 can be found in th available file.
781 But, someone proposed the idea to make it possible to
782 reconstruct a .opk from an installed package, (ie. for beaming
783 from one handheld to another). So, maybe we actually want a few
784 more fields here, (depends, suggests, etc.), so that that would
785 be guaranteed to work even in the absence of more information
786 from the available file.
788 28-MAR-03: kergoth and I discussed this yesterday. We think
789 the essential info needs to be here for all installed packages
790 because they may not appear in the Packages files on various
791 feeds. Furthermore, one should be able to install from URL or
792 local storage without requiring a Packages file from any feed.
795 pkg_formatted_field(file, pkg, "Package");
796 pkg_formatted_field(file, pkg, "Version");
797 pkg_formatted_field(file, pkg, "Depends");
798 pkg_formatted_field(file, pkg, "Recommends");
799 pkg_formatted_field(file, pkg, "Suggests");
800 pkg_formatted_field(file, pkg, "Provides");
801 pkg_formatted_field(file, pkg, "Replaces");
802 pkg_formatted_field(file, pkg, "Conflicts");
803 pkg_formatted_field(file, pkg, "Status");
804 pkg_formatted_field(file, pkg, "Essential");
805 pkg_formatted_field(file, pkg, "Architecture");
806 pkg_formatted_field(file, pkg, "Conffiles");
807 pkg_formatted_field(file, pkg, "Installed-Time");
808 pkg_formatted_field(file, pkg, "Auto-Installed");
813 * libdpkg - Debian packaging suite library routines
814 * vercmp.c - comparison of version numbers
816 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
818 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
822 if (pkg->epoch > ref_pkg->epoch) {
826 if (pkg->epoch < ref_pkg->epoch) {
830 r = verrevcmp(pkg->version, ref_pkg->version);
835 r = verrevcmp(pkg->revision, ref_pkg->revision);
843 /* assume ascii; warning: evaluates x multiple times! */
844 #define order(x) ((x) == '~' ? -1 \
847 : isalpha((x)) ? (x) \
850 static int verrevcmp(const char *val, const char *ref) {
854 while (*val || *ref) {
857 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
858 int vc= order(*val), rc= order(*ref);
859 if (vc != rc) return vc - rc;
863 while ( *val == '0' ) val++;
864 while ( *ref == '0' ) ref++;
865 while (isdigit(*val) && isdigit(*ref)) {
866 if (!first_diff) first_diff= *val - *ref;
869 if (isdigit(*val)) return 1;
870 if (isdigit(*ref)) return -1;
871 if (first_diff) return first_diff;
876 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
880 r = pkg_compare_versions(it, ref);
882 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
886 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
890 if (strcmp(op, "<<") == 0) {
894 if (strcmp(op, ">>") == 0) {
898 if (strcmp(op, "=") == 0) {
902 fprintf(stderr, "unknown operator: %s", op);
906 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
908 const pkg_t *a = *(const pkg_t**) p1;
909 const pkg_t *b = *(const pkg_t**) p2;
912 if (!a->name || !b->name) {
913 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
914 a, a->name, b, b->name);
918 namecmp = strcmp(a->name, b->name);
921 vercmp = pkg_compare_versions(a, b);
924 if (!a->arch_priority || !b->arch_priority) {
925 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
926 a, a->arch_priority, b, b->arch_priority);
929 if (a->arch_priority > b->arch_priority)
931 if (a->arch_priority < b->arch_priority)
936 int abstract_pkg_name_compare(const void *p1, const void *p2)
938 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
939 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
940 if (!a->name || !b->name) {
941 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
942 a, a->name, b, b->name);
945 return strcmp(a->name, b->name);
950 pkg_version_str_alloc(pkg_t *pkg)
956 sprintf_alloc(&version, "%d:%s-%s",
957 pkg->epoch, pkg->version, pkg->revision);
959 sprintf_alloc(&version, "%d:%s",
960 pkg->epoch, pkg->version);
963 sprintf_alloc(&version, "%s-%s",
964 pkg->version, pkg->revision);
966 version = xstrdup(pkg->version);
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 list_file = tmpfile();
1001 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1004 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1005 __FUNCTION__, pkg->local_filename, strerror(err));
1006 return pkg->installed_files;
1010 sprintf_alloc(&list_file_name, "%s/%s.list",
1011 pkg->dest->info_dir, pkg->name);
1012 if (! file_exists(list_file_name)) {
1013 free(list_file_name);
1014 return pkg->installed_files;
1017 list_file = fopen(list_file_name, "r");
1018 if (list_file == NULL) {
1019 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1020 list_file_name, strerror(errno));
1021 free(list_file_name);
1022 return pkg->installed_files;
1024 free(list_file_name);
1027 if (conf->offline_root)
1028 rootdirlen = strlen(conf->offline_root);
1033 line = file_read_line_alloc(list_file);
1040 if (pkg->state_status == SS_NOT_INSTALLED) {
1041 if (*file_name == '.') {
1044 if (*file_name == '/') {
1047 sprintf_alloc(&installed_file_name, "%s%s",
1048 pkg->dest->root_dir, file_name);
1050 if (conf->offline_root &&
1051 strncmp(conf->offline_root, file_name, rootdirlen)) {
1052 sprintf_alloc(&installed_file_name, "%s%s",
1053 conf->offline_root, file_name);
1055 // already contains root_dir as header -> ABSOLUTE
1056 sprintf_alloc(&installed_file_name, "%s", file_name);
1059 str_list_append(pkg->installed_files, installed_file_name);
1060 free(installed_file_name);
1066 return pkg->installed_files;
1069 /* XXX: CLEANUP: This function and it's counterpart,
1070 (pkg_get_installed_files), do not match our init/deinit naming
1071 convention. Nor the alloc/free convention. But, then again, neither
1072 of these conventions currrently fit the way these two functions
1074 int pkg_free_installed_files(pkg_t *pkg)
1076 pkg->installed_files_ref_cnt--;
1078 if (pkg->installed_files_ref_cnt > 0)
1081 if (pkg->installed_files) {
1082 str_list_purge(pkg->installed_files);
1085 pkg->installed_files = NULL;
1090 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1093 char *list_file_name;
1095 //I don't think pkg_free_installed_files should be called here. Jamey
1096 //pkg_free_installed_files(pkg);
1098 sprintf_alloc(&list_file_name, "%s/%s.list",
1099 pkg->dest->info_dir, pkg->name);
1100 if (!conf->noaction) {
1101 err = unlink(list_file_name);
1102 free(list_file_name);
1111 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1113 conffile_list_elt_t *iter;
1114 conffile_t *conffile;
1120 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1121 conffile = (conffile_t *)iter->data;
1123 if (strcmp(conffile->name, file_name) == 0) {
1131 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1132 const char *script, const char *args)
1141 /* XXX: CLEANUP: There must be a better way to handle maintainer
1142 scripts when running with offline_root mode and/or a dest other
1143 than '/'. I've been playing around with some clever chroot
1144 tricks and I might come up with something workable. */
1146 * Attempt to provide a restricted environment for offline operation
1147 * Need the following set as a minimum:
1148 * OPKG_OFFLINE_ROOT = absolute path to root dir
1149 * D = absolute path to root dir (for OE generated postinst)
1150 * PATH = something safe (a restricted set of utilities)
1153 if (conf->offline_root) {
1154 if (conf->offline_root_path) {
1155 setenv("PATH", conf->offline_root_path, 1);
1157 opkg_message(conf, OPKG_NOTICE,
1158 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1161 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1162 setenv("D", conf->offline_root, 1);
1165 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1166 maintainer script within a chroot environment. */
1168 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1169 have scripts in pkg->tmp_unpack_dir. */
1170 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1171 if (pkg->dest == NULL) {
1172 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1173 __FUNCTION__, pkg->name);
1176 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1178 if (pkg->tmp_unpack_dir == NULL) {
1179 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1180 __FUNCTION__, pkg->name);
1183 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1186 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1189 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1191 if (! file_exists(path)) {
1196 sprintf_alloc(&cmd, "%s %s", path, args);
1199 const char *argv[] = {"sh", "-c", cmd, NULL};
1200 err = xsystem(argv);
1205 fprintf(stderr, "%s script returned status %d\n", script, err);
1212 char *pkg_state_want_to_str(pkg_state_want_t sw)
1216 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1217 if (pkg_state_want_map[i].value == sw) {
1218 return xstrdup(pkg_state_want_map[i].str);
1222 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1224 return xstrdup("<STATE_WANT_UNKNOWN>");
1227 pkg_state_want_t pkg_state_want_from_str(char *str)
1231 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1232 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1233 return pkg_state_want_map[i].value;
1237 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1242 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1245 int len = 3; /* ok\000 is minimum */
1248 /* clear the temporary flags before converting to string */
1249 sf &= SF_NONVOLATILE_FLAGS;
1252 return xstrdup("ok");
1255 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1256 if (sf & pkg_state_flag_map[i].value) {
1257 len += strlen(pkg_state_flag_map[i].str) + 1;
1262 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1263 if (sf & pkg_state_flag_map[i].value) {
1264 strcat(str, pkg_state_flag_map[i].str);
1269 str[len-1] = 0; /* squash last comma */
1274 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1279 if (strcmp(str, "ok") == 0) {
1282 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1283 const char *sfname = pkg_state_flag_map[i].str;
1284 int sfname_len = strlen(sfname);
1285 if (strncmp(str, sfname, sfname_len) == 0) {
1286 sf |= pkg_state_flag_map[i].value;
1288 if (str[0] == ',') {
1299 char *pkg_state_status_to_str(pkg_state_status_t ss)
1303 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1304 if (pkg_state_status_map[i].value == ss) {
1305 return xstrdup(pkg_state_status_map[i].str);
1309 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1311 return xstrdup("<STATE_STATUS_UNKNOWN>");
1314 pkg_state_status_t pkg_state_status_from_str(const char *str)
1318 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1319 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1320 return pkg_state_status_map[i].value;
1324 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1326 return SS_NOT_INSTALLED;
1329 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1331 nv_pair_list_elt_t *l;
1333 if (!pkg->architecture)
1336 list_for_each_entry(l , &conf->arch_list.head, node) {
1337 nv_pair_t *nv = (nv_pair_t *)l->data;
1338 if (strcmp(nv->name, pkg->architecture) == 0) {
1339 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1344 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1348 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1350 nv_pair_list_elt_t *l;
1352 list_for_each_entry(l , &conf->arch_list.head, node) {
1353 nv_pair_t *nv = (nv_pair_t *)l->data;
1354 if (strcmp(nv->name, archname) == 0) {
1355 int priority = strtol(nv->value, NULL, 0);
1362 int pkg_info_preinstall_check(opkg_conf_t *conf)
1365 hash_table_t *pkg_hash = &conf->pkg_hash;
1366 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1367 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1369 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1370 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1371 /* update arch_priority for each package */
1372 for (i = 0; i < available_pkgs->len; i++) {
1373 pkg_t *pkg = available_pkgs->pkgs[i];
1374 int arch_priority = 1;
1377 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1378 if (pkg->architecture)
1379 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1381 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1382 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1383 pkg->arch_priority = arch_priority;
1386 for (i = 0; i < available_pkgs->len; i++) {
1387 pkg_t *pkg = available_pkgs->pkgs[i];
1388 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1389 /* clear flags and want for any uninstallable package */
1390 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1391 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1392 pkg->state_want = SW_UNKNOWN;
1393 pkg->state_flag = 0;
1396 pkg_vec_free(available_pkgs);
1398 /* update the file owner data structure */
1399 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1400 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1401 for (i = 0; i < installed_pkgs->len; i++) {
1402 pkg_t *pkg = installed_pkgs->pkgs[i];
1403 str_list_t *installed_files = pkg_get_installed_files(conf, pkg); /* this causes installed_files to be cached */
1404 str_list_elt_t *iter, *niter;
1405 if (installed_files == NULL) {
1406 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1409 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1411 iter = niter, niter = str_list_next(installed_files, iter)) {
1412 char *installed_file = (char *) iter->data;
1413 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1414 file_hash_set_file_owner(conf, installed_file, pkg);
1416 pkg_free_installed_files(pkg);
1418 pkg_vec_free(installed_pkgs);
1423 struct pkg_write_filelist_data {
1429 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1431 struct pkg_write_filelist_data *data = data_;
1432 pkg_t *entry = entry_;
1433 if (entry == data->pkg) {
1434 fprintf(data->stream, "%s\n", key);
1438 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1440 struct pkg_write_filelist_data data;
1441 char *list_file_name = NULL;
1445 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1448 opkg_message(conf, OPKG_INFO,
1449 " creating %s.list file\n", pkg->name);
1450 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1451 if (!list_file_name) {
1452 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1455 opkg_message(conf, OPKG_INFO,
1456 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1457 data.stream = fopen(list_file_name, "w");
1459 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1460 list_file_name, strerror(errno));
1465 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1466 fclose(data.stream);
1467 free(list_file_name);
1469 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1474 int pkg_write_changed_filelists(opkg_conf_t *conf)
1476 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1477 hash_table_t *pkg_hash = &conf->pkg_hash;
1483 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1484 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1485 for (i = 0; i < installed_pkgs->len; i++) {
1486 pkg_t *pkg = installed_pkgs->pkgs[i];
1487 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1488 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1489 err = pkg_write_filelist(conf, pkg);
1491 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1494 pkg_vec_free (installed_pkgs);