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)
321 char **raw, **raw_start;
325 if (err) { return err; }
327 pkg->local_filename = xstrdup(filename);
329 control_file = tmpfile();
330 err = pkg_extract_control_file_to_stream(pkg, control_file);
331 if (err) { return err; }
333 rewind(control_file);
334 raw = raw_start = read_raw_pkgs_from_stream(control_file);
335 pkg_parse_raw(pkg, &raw, NULL, NULL);
337 fclose(control_file);
348 /* Merge any new information in newpkg into oldpkg */
349 /* XXX: CLEANUP: This function shouldn't actually modify anything in
350 newpkg, but should leave it usable. This rework is so that
351 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
353 * uh, i thought that i had originally written this so that it took
354 * two pkgs and returned a new one? we can do that again... -sma
356 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
358 if (oldpkg == newpkg) {
363 oldpkg->src = newpkg->src;
365 oldpkg->dest = newpkg->dest;
366 if (!oldpkg->architecture)
367 oldpkg->architecture = xstrdup(newpkg->architecture);
368 if (!oldpkg->arch_priority)
369 oldpkg->arch_priority = newpkg->arch_priority;
370 if (!oldpkg->section)
371 oldpkg->section = xstrdup(newpkg->section);
372 if(!oldpkg->maintainer)
373 oldpkg->maintainer = xstrdup(newpkg->maintainer);
374 if(!oldpkg->description)
375 oldpkg->description = xstrdup(newpkg->description);
377 /* merge the state_flags from the new package */
378 oldpkg->state_want = newpkg->state_want;
379 oldpkg->state_status = newpkg->state_status;
380 oldpkg->state_flag = newpkg->state_flag;
382 if (oldpkg->state_want == SW_UNKNOWN)
383 oldpkg->state_want = newpkg->state_want;
384 if (oldpkg->state_status == SS_NOT_INSTALLED)
385 oldpkg->state_status = newpkg->state_status;
386 oldpkg->state_flag |= newpkg->state_flag;
389 if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
390 oldpkg->depends_str = newpkg->depends_str;
391 newpkg->depends_str = NULL;
392 oldpkg->depends_count = newpkg->depends_count;
393 newpkg->depends_count = 0;
395 oldpkg->depends = newpkg->depends;
396 newpkg->depends = NULL;
398 oldpkg->pre_depends_str = newpkg->pre_depends_str;
399 newpkg->pre_depends_str = NULL;
400 oldpkg->pre_depends_count = newpkg->pre_depends_count;
401 newpkg->pre_depends_count = 0;
403 oldpkg->recommends_str = newpkg->recommends_str;
404 newpkg->recommends_str = NULL;
405 oldpkg->recommends_count = newpkg->recommends_count;
406 newpkg->recommends_count = 0;
408 oldpkg->suggests_str = newpkg->suggests_str;
409 newpkg->suggests_str = NULL;
410 oldpkg->suggests_count = newpkg->suggests_count;
411 newpkg->suggests_count = 0;
414 if (!oldpkg->provides_str) {
415 oldpkg->provides_str = newpkg->provides_str;
416 newpkg->provides_str = NULL;
417 oldpkg->provides_count = newpkg->provides_count;
418 newpkg->provides_count = 0;
420 if (!oldpkg->provides) {
421 oldpkg->provides = newpkg->provides;
422 newpkg->provides = NULL;
426 if (!oldpkg->conflicts_str) {
427 oldpkg->conflicts_str = newpkg->conflicts_str;
428 newpkg->conflicts_str = NULL;
429 oldpkg->conflicts_count = newpkg->conflicts_count;
430 newpkg->conflicts_count = 0;
432 oldpkg->conflicts = newpkg->conflicts;
433 newpkg->conflicts = NULL;
436 if (!oldpkg->replaces_str) {
437 oldpkg->replaces_str = newpkg->replaces_str;
438 newpkg->replaces_str = NULL;
439 oldpkg->replaces_count = newpkg->replaces_count;
440 newpkg->replaces_count = 0;
442 oldpkg->replaces = newpkg->replaces;
443 newpkg->replaces = NULL;
446 if (!oldpkg->filename)
447 oldpkg->filename = xstrdup(newpkg->filename);
448 if (!oldpkg->local_filename)
449 oldpkg->local_filename = xstrdup(newpkg->local_filename);
450 if (!oldpkg->tmp_unpack_dir)
451 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
453 oldpkg->md5sum = xstrdup(newpkg->md5sum);
454 #if defined HAVE_SHA256
455 if (!oldpkg->sha256sum)
456 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
459 oldpkg->size = xstrdup(newpkg->size);
460 if (!oldpkg->installed_size)
461 oldpkg->installed_size = xstrdup(newpkg->installed_size);
462 if (!oldpkg->priority)
463 oldpkg->priority = xstrdup(newpkg->priority);
465 oldpkg->source = xstrdup(newpkg->source);
466 if (nv_pair_list_empty(&oldpkg->conffiles)){
467 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
468 conffile_list_init(&newpkg->conffiles);
470 if (!oldpkg->installed_files){
471 oldpkg->installed_files = newpkg->installed_files;
472 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
473 newpkg->installed_files = NULL;
475 if (!oldpkg->essential)
476 oldpkg->essential = newpkg->essential;
481 abstract_pkg_t *abstract_pkg_new(void)
483 abstract_pkg_t * ab_pkg;
485 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
487 if (ab_pkg == NULL) {
488 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
492 if ( abstract_pkg_init(ab_pkg) < 0 )
498 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
500 ab_pkg->provided_by = abstract_pkg_vec_alloc();
501 if (ab_pkg->provided_by==NULL){
504 ab_pkg->dependencies_checked = 0;
505 ab_pkg->state_status = SS_NOT_INSTALLED;
510 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
513 char **raw_start=NULL;
515 size_t str_size = strlen(pkg->dest->info_dir)+strlen(pkg->name)+12;
516 temp_str = (char *) alloca (str_size);
517 memset(temp_str, 0 , str_size);
519 if (temp_str == NULL ){
520 opkg_message(conf, OPKG_INFO, "Out of memory in %s\n", __FUNCTION__);
523 sprintf( temp_str,"%s/%s.control",pkg->dest->info_dir,pkg->name);
525 raw = raw_start = read_raw_pkgs_from_file(temp_str);
527 opkg_message(conf, OPKG_ERROR, "Unable to open the control file in %s\n", __FUNCTION__);
532 if (!pkg_valorize_other_field(pkg, &raw ) == 0) {
533 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
548 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
552 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
553 goto UNKNOWN_FMT_FIELD;
560 if (strcasecmp(field, "Architecture") == 0) {
561 if (pkg->architecture) {
562 fprintf(fp, "Architecture: %s\n", pkg->architecture);
564 } else if (strcasecmp(field, "Auto-Installed") == 0) {
565 if (pkg->auto_installed)
566 fprintf(fp, "Auto-Installed: yes\n");
568 goto UNKNOWN_FMT_FIELD;
573 if (strcasecmp(field, "Conffiles") == 0) {
574 conffile_list_elt_t *iter;
576 if (nv_pair_list_empty(&pkg->conffiles))
579 fprintf(fp, "Conffiles:\n");
580 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
581 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
582 fprintf(fp, "%s %s\n",
583 ((conffile_t *)iter->data)->name,
584 ((conffile_t *)iter->data)->value);
587 } else if (strcasecmp(field, "Conflicts") == 0) {
588 if (pkg->conflicts_count) {
589 fprintf(fp, "Conflicts:");
590 for(i = 0; i < pkg->conflicts_count; i++) {
591 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
596 goto UNKNOWN_FMT_FIELD;
601 if (strcasecmp(field, "Depends") == 0) {
602 if (pkg->depends_count) {
603 fprintf(fp, "Depends:");
604 for(i = 0; i < pkg->depends_count; i++) {
605 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
609 } else if (strcasecmp(field, "Description") == 0) {
610 if (pkg->description) {
611 fprintf(fp, "Description: %s\n", pkg->description);
614 goto UNKNOWN_FMT_FIELD;
619 if (pkg->essential) {
620 fprintf(fp, "Essential: yes\n");
626 fprintf(fp, "Filename: %s\n", pkg->filename);
631 if (strcasecmp(field, "Installed-Size") == 0) {
632 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
633 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
634 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
639 if (strcasecmp(field, "Maintainer") == 0) {
640 if (pkg->maintainer) {
641 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
643 } else if (strcasecmp(field, "MD5sum") == 0) {
645 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
648 goto UNKNOWN_FMT_FIELD;
653 if (strcasecmp(field, "Package") == 0) {
654 fprintf(fp, "Package: %s\n", pkg->name);
655 } else if (strcasecmp(field, "Priority") == 0) {
656 fprintf(fp, "Priority: %s\n", pkg->priority);
657 } else if (strcasecmp(field, "Provides") == 0) {
658 if (pkg->provides_count) {
659 fprintf(fp, "Provides:");
660 for(i = 0; i < pkg->provides_count-1; i++) {
661 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->provides_str[i]);
666 goto UNKNOWN_FMT_FIELD;
671 if (strcasecmp (field, "Replaces") == 0) {
672 if (pkg->replaces_count) {
673 fprintf(fp, "Replaces:");
674 for (i = 0; i < pkg->replaces_count; i++) {
675 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
679 } else if (strcasecmp (field, "Recommends") == 0) {
680 if (pkg->recommends_count) {
681 fprintf(fp, "Recommends:");
682 for(i = 0; i < pkg->recommends_count; i++) {
683 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
688 goto UNKNOWN_FMT_FIELD;
693 if (strcasecmp(field, "Section") == 0) {
695 fprintf(fp, "Section: %s\n", pkg->section);
697 #if defined HAVE_SHA256
698 } else if (strcasecmp(field, "SHA256sum") == 0) {
699 if (pkg->sha256sum) {
700 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
703 } else if (strcasecmp(field, "Size") == 0) {
705 fprintf(fp, "Size: %s\n", pkg->size);
707 } else if (strcasecmp(field, "Source") == 0) {
709 fprintf(fp, "Source: %s\n", pkg->source);
711 } else if (strcasecmp(field, "Status") == 0) {
712 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
713 char *pstat = pkg_state_status_to_str(pkg->state_status);
714 char *pwant = pkg_state_want_to_str(pkg->state_want);
716 if (pflag == NULL || pstat == NULL || pwant == NULL)
719 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
724 } else if (strcasecmp(field, "Suggests") == 0) {
725 if (pkg->suggests_count) {
726 fprintf(fp, "Suggests:");
727 for(i = 0; i < pkg->suggests_count; i++) {
728 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
733 goto UNKNOWN_FMT_FIELD;
738 if (strcasecmp(field, "Tags") == 0) {
740 fprintf(fp, "Tags: %s\n", pkg->tags);
747 char *version = pkg_version_str_alloc(pkg);
750 fprintf(fp, "Version: %s\n", version);
755 goto UNKNOWN_FMT_FIELD;
761 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
764 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
766 pkg_formatted_field(fp, pkg, "Package");
767 pkg_formatted_field(fp, pkg, "Version");
768 pkg_formatted_field(fp, pkg, "Depends");
769 pkg_formatted_field(fp, pkg, "Recommends");
770 pkg_formatted_field(fp, pkg, "Suggests");
771 pkg_formatted_field(fp, pkg, "Provides");
772 pkg_formatted_field(fp, pkg, "Replaces");
773 pkg_formatted_field(fp, pkg, "Conflicts");
774 pkg_formatted_field(fp, pkg, "Status");
775 pkg_formatted_field(fp, pkg, "Section");
776 pkg_formatted_field(fp, pkg, "Essential");
777 pkg_formatted_field(fp, pkg, "Architecture");
778 pkg_formatted_field(fp, pkg, "Maintainer");
779 pkg_formatted_field(fp, pkg, "MD5sum");
780 pkg_formatted_field(fp, pkg, "Size");
781 pkg_formatted_field(fp, pkg, "Filename");
782 pkg_formatted_field(fp, pkg, "Conffiles");
783 pkg_formatted_field(fp, pkg, "Source");
784 pkg_formatted_field(fp, pkg, "Description");
785 pkg_formatted_field(fp, pkg, "Installed-Time");
786 pkg_formatted_field(fp, pkg, "Tags");
790 void pkg_print_status(pkg_t * pkg, FILE * file)
796 /* XXX: QUESTION: Do we actually want more fields here? The
797 original idea was to save space by installing only what was
798 needed for actual computation, (package, version, status,
799 essential, conffiles). The assumption is that all other fields
800 can be found in th available file.
802 But, someone proposed the idea to make it possible to
803 reconstruct a .opk from an installed package, (ie. for beaming
804 from one handheld to another). So, maybe we actually want a few
805 more fields here, (depends, suggests, etc.), so that that would
806 be guaranteed to work even in the absence of more information
807 from the available file.
809 28-MAR-03: kergoth and I discussed this yesterday. We think
810 the essential info needs to be here for all installed packages
811 because they may not appear in the Packages files on various
812 feeds. Furthermore, one should be able to install from URL or
813 local storage without requiring a Packages file from any feed.
816 pkg_formatted_field(file, pkg, "Package");
817 pkg_formatted_field(file, pkg, "Version");
818 pkg_formatted_field(file, pkg, "Depends");
819 pkg_formatted_field(file, pkg, "Recommends");
820 pkg_formatted_field(file, pkg, "Suggests");
821 pkg_formatted_field(file, pkg, "Provides");
822 pkg_formatted_field(file, pkg, "Replaces");
823 pkg_formatted_field(file, pkg, "Conflicts");
824 pkg_formatted_field(file, pkg, "Status");
825 pkg_formatted_field(file, pkg, "Essential");
826 pkg_formatted_field(file, pkg, "Architecture");
827 pkg_formatted_field(file, pkg, "Conffiles");
828 pkg_formatted_field(file, pkg, "Installed-Time");
829 pkg_formatted_field(file, pkg, "Auto-Installed");
834 * libdpkg - Debian packaging suite library routines
835 * vercmp.c - comparison of version numbers
837 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
839 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
843 if (pkg->epoch > ref_pkg->epoch) {
847 if (pkg->epoch < ref_pkg->epoch) {
851 r = verrevcmp(pkg->version, ref_pkg->version);
856 r = verrevcmp(pkg->revision, ref_pkg->revision);
864 /* assume ascii; warning: evaluates x multiple times! */
865 #define order(x) ((x) == '~' ? -1 \
868 : isalpha((x)) ? (x) \
871 static int verrevcmp(const char *val, const char *ref) {
875 while (*val || *ref) {
878 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
879 int vc= order(*val), rc= order(*ref);
880 if (vc != rc) return vc - rc;
884 while ( *val == '0' ) val++;
885 while ( *ref == '0' ) ref++;
886 while (isdigit(*val) && isdigit(*ref)) {
887 if (!first_diff) first_diff= *val - *ref;
890 if (isdigit(*val)) return 1;
891 if (isdigit(*ref)) return -1;
892 if (first_diff) return first_diff;
897 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
901 r = pkg_compare_versions(it, ref);
903 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
907 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
911 if (strcmp(op, "<<") == 0) {
915 if (strcmp(op, ">>") == 0) {
919 if (strcmp(op, "=") == 0) {
923 fprintf(stderr, "unknown operator: %s", op);
927 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
929 const pkg_t *a = *(const pkg_t**) p1;
930 const pkg_t *b = *(const pkg_t**) p2;
933 if (!a->name || !b->name) {
934 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
935 a, a->name, b, b->name);
939 namecmp = strcmp(a->name, b->name);
942 vercmp = pkg_compare_versions(a, b);
945 if (!a->arch_priority || !b->arch_priority) {
946 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
947 a, a->arch_priority, b, b->arch_priority);
950 if (a->arch_priority > b->arch_priority)
952 if (a->arch_priority < b->arch_priority)
957 int abstract_pkg_name_compare(const void *p1, const void *p2)
959 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
960 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
961 if (!a->name || !b->name) {
962 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
963 a, a->name, b, b->name);
966 return strcmp(a->name, b->name);
970 char *pkg_version_str_alloc(pkg_t *pkg)
972 char *complete_version;
977 sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
979 epoch_str = xstrdup("");
982 if (pkg->revision && strlen(pkg->revision)) {
983 sprintf_alloc(&revision_str, "-%s", pkg->revision);
985 revision_str = xstrdup("");
989 sprintf_alloc(&complete_version, "%s%s%s",
990 epoch_str, pkg->version, revision_str);
995 return complete_version;
998 str_list_t *pkg_get_installed_files(pkg_t *pkg)
1001 char *list_file_name = NULL;
1002 FILE *list_file = NULL;
1004 char *installed_file_name;
1007 pkg->installed_files_ref_cnt++;
1009 if (pkg->installed_files) {
1010 return pkg->installed_files;
1013 pkg->installed_files = str_list_alloc();
1015 /* For uninstalled packages, get the file list directly from the package.
1016 For installed packages, look at the package.list file in the database.
1018 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1019 if (pkg->local_filename == NULL) {
1020 return pkg->installed_files;
1022 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1023 file. In other words, change deb_extract so that it can
1024 simply return the file list as a char *[] rather than
1025 insisting on writing in to a FILE * as it does now. */
1026 list_file = tmpfile();
1027 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1030 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1031 __FUNCTION__, pkg->local_filename, strerror(err));
1032 return pkg->installed_files;
1036 sprintf_alloc(&list_file_name, "%s/%s.list",
1037 pkg->dest->info_dir, pkg->name);
1038 if (! file_exists(list_file_name)) {
1039 free(list_file_name);
1040 return pkg->installed_files;
1043 list_file = fopen(list_file_name, "r");
1044 if (list_file == NULL) {
1045 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1046 list_file_name, strerror(errno));
1047 free(list_file_name);
1048 return pkg->installed_files;
1050 free(list_file_name);
1053 rootdirlen = strlen( pkg->dest->root_dir );
1057 line = file_read_line_alloc(list_file);
1064 /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1065 if( strncmp( pkg->dest->root_dir,
1068 if (*file_name == '.') {
1071 if (*file_name == '/') {
1075 /* Freed in pkg_free_installed_files */
1076 sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1078 // already contains root_dir as header -> ABSOLUTE
1079 sprintf_alloc(&installed_file_name, "%s", file_name);
1081 str_list_append(pkg->installed_files, installed_file_name);
1082 free(installed_file_name);
1088 return pkg->installed_files;
1091 /* XXX: CLEANUP: This function and it's counterpart,
1092 (pkg_get_installed_files), do not match our init/deinit naming
1093 convention. Nor the alloc/free convention. But, then again, neither
1094 of these conventions currrently fit the way these two functions
1096 int pkg_free_installed_files(pkg_t *pkg)
1098 pkg->installed_files_ref_cnt--;
1100 if (pkg->installed_files_ref_cnt > 0)
1103 if (pkg->installed_files) {
1104 str_list_purge(pkg->installed_files);
1107 pkg->installed_files = NULL;
1112 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1115 char *list_file_name;
1117 //I don't think pkg_free_installed_files should be called here. Jamey
1118 //pkg_free_installed_files(pkg);
1120 sprintf_alloc(&list_file_name, "%s/%s.list",
1121 pkg->dest->info_dir, pkg->name);
1122 if (!conf->noaction) {
1123 err = unlink(list_file_name);
1124 free(list_file_name);
1133 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1135 conffile_list_elt_t *iter;
1136 conffile_t *conffile;
1142 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1143 conffile = (conffile_t *)iter->data;
1145 if (strcmp(conffile->name, file_name) == 0) {
1153 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1154 const char *script, const char *args)
1163 /* XXX: CLEANUP: There must be a better way to handle maintainer
1164 scripts when running with offline_root mode and/or a dest other
1165 than '/'. I've been playing around with some clever chroot
1166 tricks and I might come up with something workable. */
1168 * Attempt to provide a restricted environment for offline operation
1169 * Need the following set as a minimum:
1170 * OPKG_OFFLINE_ROOT = absolute path to root dir
1171 * D = absolute path to root dir (for OE generated postinst)
1172 * PATH = something safe (a restricted set of utilities)
1175 if (conf->offline_root) {
1176 if (conf->offline_root_path) {
1177 setenv("PATH", conf->offline_root_path, 1);
1179 opkg_message(conf, OPKG_NOTICE,
1180 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1183 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1184 setenv("D", conf->offline_root, 1);
1187 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1188 maintainer script within a chroot environment. */
1190 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1191 have scripts in pkg->tmp_unpack_dir. */
1192 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1193 if (pkg->dest == NULL) {
1194 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1195 __FUNCTION__, pkg->name);
1198 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1200 if (pkg->tmp_unpack_dir == NULL) {
1201 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1202 __FUNCTION__, pkg->name);
1205 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1208 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1211 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1213 if (! file_exists(path)) {
1218 sprintf_alloc(&cmd, "%s %s", path, args);
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(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);