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 oldpkg->provides = newpkg->provides;
421 newpkg->provides = NULL;
424 if (!oldpkg->conflicts_str) {
425 oldpkg->conflicts_str = newpkg->conflicts_str;
426 newpkg->conflicts_str = NULL;
427 oldpkg->conflicts_count = newpkg->conflicts_count;
428 newpkg->conflicts_count = 0;
430 oldpkg->conflicts = newpkg->conflicts;
431 newpkg->conflicts = NULL;
434 if (!oldpkg->replaces_str) {
435 oldpkg->replaces_str = newpkg->replaces_str;
436 newpkg->replaces_str = NULL;
437 oldpkg->replaces_count = newpkg->replaces_count;
438 newpkg->replaces_count = 0;
440 oldpkg->replaces = newpkg->replaces;
441 newpkg->replaces = NULL;
444 if (!oldpkg->filename)
445 oldpkg->filename = xstrdup(newpkg->filename);
446 if (!oldpkg->local_filename)
447 oldpkg->local_filename = xstrdup(newpkg->local_filename);
448 if (!oldpkg->tmp_unpack_dir)
449 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
451 oldpkg->md5sum = xstrdup(newpkg->md5sum);
452 #if defined HAVE_SHA256
453 if (!oldpkg->sha256sum)
454 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
457 oldpkg->size = xstrdup(newpkg->size);
458 if (!oldpkg->installed_size)
459 oldpkg->installed_size = xstrdup(newpkg->installed_size);
460 if (!oldpkg->priority)
461 oldpkg->priority = xstrdup(newpkg->priority);
463 oldpkg->source = xstrdup(newpkg->source);
464 if (nv_pair_list_empty(&oldpkg->conffiles)){
465 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
466 conffile_list_init(&newpkg->conffiles);
468 if (!oldpkg->installed_files){
469 oldpkg->installed_files = newpkg->installed_files;
470 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
471 newpkg->installed_files = NULL;
473 if (!oldpkg->essential)
474 oldpkg->essential = newpkg->essential;
479 abstract_pkg_t *abstract_pkg_new(void)
481 abstract_pkg_t * ab_pkg;
483 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
485 if (ab_pkg == NULL) {
486 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
490 if ( abstract_pkg_init(ab_pkg) < 0 )
496 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
498 ab_pkg->provided_by = abstract_pkg_vec_alloc();
499 if (ab_pkg->provided_by==NULL){
502 ab_pkg->dependencies_checked = 0;
503 ab_pkg->state_status = SS_NOT_INSTALLED;
508 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
511 char **raw_start=NULL;
513 size_t str_size = strlen(pkg->dest->info_dir)+strlen(pkg->name)+12;
514 temp_str = (char *) alloca (str_size);
515 memset(temp_str, 0 , str_size);
517 if (temp_str == NULL ){
518 opkg_message(conf, OPKG_INFO, "Out of memory in %s\n", __FUNCTION__);
521 sprintf( temp_str,"%s/%s.control",pkg->dest->info_dir,pkg->name);
523 raw = raw_start = read_raw_pkgs_from_file(temp_str);
525 opkg_message(conf, OPKG_ERROR, "Unable to open the control file in %s\n", __FUNCTION__);
530 if (!pkg_valorize_other_field(pkg, &raw ) == 0) {
531 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
546 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
549 int flag_provide_false = 0;
551 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
552 goto UNKNOWN_FMT_FIELD;
559 if (strcasecmp(field, "Architecture") == 0) {
560 if (pkg->architecture) {
561 fprintf(fp, "Architecture: %s\n", pkg->architecture);
563 } else if (strcasecmp(field, "Auto-Installed") == 0) {
564 if (pkg->auto_installed)
565 fprintf(fp, "Auto-Installed: yes\n");
567 goto UNKNOWN_FMT_FIELD;
572 if (strcasecmp(field, "Conffiles") == 0) {
573 conffile_list_elt_t *iter;
575 if (nv_pair_list_empty(&pkg->conffiles))
578 fprintf(fp, "Conffiles:\n");
579 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
580 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
581 fprintf(fp, "%s %s\n",
582 ((conffile_t *)iter->data)->name,
583 ((conffile_t *)iter->data)->value);
586 } else if (strcasecmp(field, "Conflicts") == 0) {
587 if (pkg->conflicts_count) {
588 fprintf(fp, "Conflicts:");
589 for(i = 0; i < pkg->conflicts_count; i++) {
590 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
595 goto UNKNOWN_FMT_FIELD;
600 if (strcasecmp(field, "Depends") == 0) {
601 if (pkg->depends_count) {
602 fprintf(fp, "Depends:");
603 for(i = 0; i < pkg->depends_count; i++) {
604 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
608 } else if (strcasecmp(field, "Description") == 0) {
609 if (pkg->description) {
610 fprintf(fp, "Description: %s\n", pkg->description);
613 goto UNKNOWN_FMT_FIELD;
618 if (pkg->essential) {
619 fprintf(fp, "Essential: yes\n");
625 fprintf(fp, "Filename: %s\n", pkg->filename);
630 if (strcasecmp(field, "Installed-Size") == 0) {
631 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
632 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
633 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
638 if (strcasecmp(field, "Maintainer") == 0) {
639 if (pkg->maintainer) {
640 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
642 } else if (strcasecmp(field, "MD5sum") == 0) {
644 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
647 goto UNKNOWN_FMT_FIELD;
652 if (strcasecmp(field, "Package") == 0) {
653 fprintf(fp, "Package: %s\n", pkg->name);
654 } else if (strcasecmp(field, "Priority") == 0) {
655 fprintf(fp, "Priority: %s\n", pkg->priority);
656 } else if (strcasecmp(field, "Provides") == 0) {
657 if (pkg->provides_count) {
658 /* Here we check if the opkg_internal_use_only is used, and we discard it.*/
659 for ( i=0; i < pkg->provides_count; i++ ){
660 if (strstr(pkg->provides_str[i],"opkg_internal_use_only")!=NULL) {
661 memset (pkg->provides_str[i],'\x0',strlen(pkg->provides_str[i])); /* Pigi clear my trick flag, just in case */
662 flag_provide_false = 1;
665 if ( !flag_provide_false || /* Pigi there is not my trick flag */
666 ((flag_provide_false) && (pkg->provides_count > 1))){ /* Pigi There is, but we also have others Provides */
667 fprintf(fp, "Provides:");
668 for(i = 0; i < pkg->provides_count; i++) {
669 if (strlen(pkg->provides_str[i])>0) {
670 fprintf(fp, "%s %s", i == 1 ? "" : ",", pkg->provides_str[i]);
677 goto UNKNOWN_FMT_FIELD;
682 if (strcasecmp (field, "Replaces") == 0) {
683 if (pkg->replaces_count) {
684 fprintf(fp, "Replaces:");
685 for (i = 0; i < pkg->replaces_count; i++) {
686 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
690 } else if (strcasecmp (field, "Recommends") == 0) {
691 if (pkg->recommends_count) {
692 fprintf(fp, "Recommends:");
693 for(i = 0; i < pkg->recommends_count; i++) {
694 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
699 goto UNKNOWN_FMT_FIELD;
704 if (strcasecmp(field, "Section") == 0) {
706 fprintf(fp, "Section: %s\n", pkg->section);
708 #if defined HAVE_SHA256
709 } else if (strcasecmp(field, "SHA256sum") == 0) {
710 if (pkg->sha256sum) {
711 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
714 } else if (strcasecmp(field, "Size") == 0) {
716 fprintf(fp, "Size: %s\n", pkg->size);
718 } else if (strcasecmp(field, "Source") == 0) {
720 fprintf(fp, "Source: %s\n", pkg->source);
722 } else if (strcasecmp(field, "Status") == 0) {
723 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
724 char *pstat = pkg_state_status_to_str(pkg->state_status);
725 char *pwant = pkg_state_want_to_str(pkg->state_want);
727 if (pflag == NULL || pstat == NULL || pwant == NULL)
730 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
735 } else if (strcasecmp(field, "Suggests") == 0) {
736 if (pkg->suggests_count) {
737 fprintf(fp, "Suggests:");
738 for(i = 0; i < pkg->suggests_count; i++) {
739 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
744 goto UNKNOWN_FMT_FIELD;
749 if (strcasecmp(field, "Tags") == 0) {
751 fprintf(fp, "Tags: %s\n", pkg->tags);
758 char *version = pkg_version_str_alloc(pkg);
761 fprintf(fp, "Version: %s\n", version);
766 goto UNKNOWN_FMT_FIELD;
772 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
775 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
777 pkg_formatted_field(fp, pkg, "Package");
778 pkg_formatted_field(fp, pkg, "Version");
779 pkg_formatted_field(fp, pkg, "Depends");
780 pkg_formatted_field(fp, pkg, "Recommends");
781 pkg_formatted_field(fp, pkg, "Suggests");
782 pkg_formatted_field(fp, pkg, "Provides");
783 pkg_formatted_field(fp, pkg, "Replaces");
784 pkg_formatted_field(fp, pkg, "Conflicts");
785 pkg_formatted_field(fp, pkg, "Status");
786 pkg_formatted_field(fp, pkg, "Section");
787 pkg_formatted_field(fp, pkg, "Essential");
788 pkg_formatted_field(fp, pkg, "Architecture");
789 pkg_formatted_field(fp, pkg, "Maintainer");
790 pkg_formatted_field(fp, pkg, "MD5sum");
791 pkg_formatted_field(fp, pkg, "Size");
792 pkg_formatted_field(fp, pkg, "Filename");
793 pkg_formatted_field(fp, pkg, "Conffiles");
794 pkg_formatted_field(fp, pkg, "Source");
795 pkg_formatted_field(fp, pkg, "Description");
796 pkg_formatted_field(fp, pkg, "Installed-Time");
797 pkg_formatted_field(fp, pkg, "Tags");
801 void pkg_print_status(pkg_t * pkg, FILE * file)
807 /* XXX: QUESTION: Do we actually want more fields here? The
808 original idea was to save space by installing only what was
809 needed for actual computation, (package, version, status,
810 essential, conffiles). The assumption is that all other fields
811 can be found in th available file.
813 But, someone proposed the idea to make it possible to
814 reconstruct a .opk from an installed package, (ie. for beaming
815 from one handheld to another). So, maybe we actually want a few
816 more fields here, (depends, suggests, etc.), so that that would
817 be guaranteed to work even in the absence of more information
818 from the available file.
820 28-MAR-03: kergoth and I discussed this yesterday. We think
821 the essential info needs to be here for all installed packages
822 because they may not appear in the Packages files on various
823 feeds. Furthermore, one should be able to install from URL or
824 local storage without requiring a Packages file from any feed.
827 pkg_formatted_field(file, pkg, "Package");
828 pkg_formatted_field(file, pkg, "Version");
829 pkg_formatted_field(file, pkg, "Depends");
830 pkg_formatted_field(file, pkg, "Recommends");
831 pkg_formatted_field(file, pkg, "Suggests");
832 pkg_formatted_field(file, pkg, "Provides");
833 pkg_formatted_field(file, pkg, "Replaces");
834 pkg_formatted_field(file, pkg, "Conflicts");
835 pkg_formatted_field(file, pkg, "Status");
836 pkg_formatted_field(file, pkg, "Essential");
837 pkg_formatted_field(file, pkg, "Architecture");
838 pkg_formatted_field(file, pkg, "Conffiles");
839 pkg_formatted_field(file, pkg, "Installed-Time");
840 pkg_formatted_field(file, pkg, "Auto-Installed");
845 * libdpkg - Debian packaging suite library routines
846 * vercmp.c - comparison of version numbers
848 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
850 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
854 if (pkg->epoch > ref_pkg->epoch) {
858 if (pkg->epoch < ref_pkg->epoch) {
862 r = verrevcmp(pkg->version, ref_pkg->version);
867 r = verrevcmp(pkg->revision, ref_pkg->revision);
875 /* assume ascii; warning: evaluates x multiple times! */
876 #define order(x) ((x) == '~' ? -1 \
879 : isalpha((x)) ? (x) \
882 static int verrevcmp(const char *val, const char *ref) {
886 while (*val || *ref) {
889 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
890 int vc= order(*val), rc= order(*ref);
891 if (vc != rc) return vc - rc;
895 while ( *val == '0' ) val++;
896 while ( *ref == '0' ) ref++;
897 while (isdigit(*val) && isdigit(*ref)) {
898 if (!first_diff) first_diff= *val - *ref;
901 if (isdigit(*val)) return 1;
902 if (isdigit(*ref)) return -1;
903 if (first_diff) return first_diff;
908 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
912 r = pkg_compare_versions(it, ref);
914 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
918 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
922 if (strcmp(op, "<<") == 0) {
926 if (strcmp(op, ">>") == 0) {
930 if (strcmp(op, "=") == 0) {
934 fprintf(stderr, "unknown operator: %s", op);
938 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
940 const pkg_t *a = *(const pkg_t**) p1;
941 const pkg_t *b = *(const pkg_t**) p2;
944 if (!a->name || !b->name) {
945 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
946 a, a->name, b, b->name);
950 namecmp = strcmp(a->name, b->name);
953 vercmp = pkg_compare_versions(a, b);
956 if (!a->arch_priority || !b->arch_priority) {
957 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
958 a, a->arch_priority, b, b->arch_priority);
961 if (a->arch_priority > b->arch_priority)
963 if (a->arch_priority < b->arch_priority)
968 int abstract_pkg_name_compare(const void *p1, const void *p2)
970 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
971 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
972 if (!a->name || !b->name) {
973 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
974 a, a->name, b, b->name);
977 return strcmp(a->name, b->name);
981 char *pkg_version_str_alloc(pkg_t *pkg)
983 char *complete_version;
988 sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
990 epoch_str = xstrdup("");
993 if (pkg->revision && strlen(pkg->revision)) {
994 sprintf_alloc(&revision_str, "-%s", pkg->revision);
996 revision_str = xstrdup("");
1000 sprintf_alloc(&complete_version, "%s%s%s",
1001 epoch_str, pkg->version, revision_str);
1006 return complete_version;
1009 str_list_t *pkg_get_installed_files(pkg_t *pkg)
1012 char *list_file_name = NULL;
1013 FILE *list_file = NULL;
1015 char *installed_file_name;
1018 pkg->installed_files_ref_cnt++;
1020 if (pkg->installed_files) {
1021 return pkg->installed_files;
1024 pkg->installed_files = str_list_alloc();
1026 /* For uninstalled packages, get the file list directly from the package.
1027 For installed packages, look at the package.list file in the database.
1029 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1030 if (pkg->local_filename == NULL) {
1031 return pkg->installed_files;
1033 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1034 file. In other words, change deb_extract so that it can
1035 simply return the file list as a char *[] rather than
1036 insisting on writing in to a FILE * as it does now. */
1037 list_file = tmpfile();
1038 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1041 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1042 __FUNCTION__, pkg->local_filename, strerror(err));
1043 return pkg->installed_files;
1047 sprintf_alloc(&list_file_name, "%s/%s.list",
1048 pkg->dest->info_dir, pkg->name);
1049 if (! file_exists(list_file_name)) {
1050 free(list_file_name);
1051 return pkg->installed_files;
1054 list_file = fopen(list_file_name, "r");
1055 if (list_file == NULL) {
1056 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1057 list_file_name, strerror(errno));
1058 free(list_file_name);
1059 return pkg->installed_files;
1061 free(list_file_name);
1064 rootdirlen = strlen( pkg->dest->root_dir );
1068 line = file_read_line_alloc(list_file);
1075 /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1076 if( strncmp( pkg->dest->root_dir,
1079 if (*file_name == '.') {
1082 if (*file_name == '/') {
1086 /* Freed in pkg_free_installed_files */
1087 sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1089 // already contains root_dir as header -> ABSOLUTE
1090 sprintf_alloc(&installed_file_name, "%s", file_name);
1092 str_list_append(pkg->installed_files, installed_file_name);
1093 free(installed_file_name);
1099 return pkg->installed_files;
1102 /* XXX: CLEANUP: This function and it's counterpart,
1103 (pkg_get_installed_files), do not match our init/deinit naming
1104 convention. Nor the alloc/free convention. But, then again, neither
1105 of these conventions currrently fit the way these two functions
1107 int pkg_free_installed_files(pkg_t *pkg)
1109 pkg->installed_files_ref_cnt--;
1111 if (pkg->installed_files_ref_cnt > 0)
1114 if (pkg->installed_files) {
1115 str_list_purge(pkg->installed_files);
1118 pkg->installed_files = NULL;
1123 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1126 char *list_file_name;
1128 //I don't think pkg_free_installed_files should be called here. Jamey
1129 //pkg_free_installed_files(pkg);
1131 sprintf_alloc(&list_file_name, "%s/%s.list",
1132 pkg->dest->info_dir, pkg->name);
1133 if (!conf->noaction) {
1134 err = unlink(list_file_name);
1135 free(list_file_name);
1144 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1146 conffile_list_elt_t *iter;
1147 conffile_t *conffile;
1153 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1154 conffile = (conffile_t *)iter->data;
1156 if (strcmp(conffile->name, file_name) == 0) {
1164 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1165 const char *script, const char *args)
1174 /* XXX: CLEANUP: There must be a better way to handle maintainer
1175 scripts when running with offline_root mode and/or a dest other
1176 than '/'. I've been playing around with some clever chroot
1177 tricks and I might come up with something workable. */
1179 * Attempt to provide a restricted environment for offline operation
1180 * Need the following set as a minimum:
1181 * OPKG_OFFLINE_ROOT = absolute path to root dir
1182 * D = absolute path to root dir (for OE generated postinst)
1183 * PATH = something safe (a restricted set of utilities)
1186 if (conf->offline_root) {
1187 if (conf->offline_root_path) {
1188 setenv("PATH", conf->offline_root_path, 1);
1190 opkg_message(conf, OPKG_NOTICE,
1191 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1194 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1195 setenv("D", conf->offline_root, 1);
1198 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1199 maintainer script within a chroot environment. */
1201 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1202 have scripts in pkg->tmp_unpack_dir. */
1203 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1204 if (pkg->dest == NULL) {
1205 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1206 __FUNCTION__, pkg->name);
1209 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1211 if (pkg->tmp_unpack_dir == NULL) {
1212 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1213 __FUNCTION__, pkg->name);
1216 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1219 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1222 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1224 if (! file_exists(path)) {
1229 sprintf_alloc(&cmd, "%s %s", path, args);
1236 fprintf(stderr, "%s script returned status %d\n", script, err);
1243 char *pkg_state_want_to_str(pkg_state_want_t sw)
1247 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1248 if (pkg_state_want_map[i].value == sw) {
1249 return xstrdup(pkg_state_want_map[i].str);
1253 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1255 return xstrdup("<STATE_WANT_UNKNOWN>");
1258 pkg_state_want_t pkg_state_want_from_str(char *str)
1262 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1263 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1264 return pkg_state_want_map[i].value;
1268 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1273 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1276 int len = 3; /* ok\000 is minimum */
1279 /* clear the temporary flags before converting to string */
1280 sf &= SF_NONVOLATILE_FLAGS;
1283 return xstrdup("ok");
1286 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1287 if (sf & pkg_state_flag_map[i].value) {
1288 len += strlen(pkg_state_flag_map[i].str) + 1;
1293 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1294 if (sf & pkg_state_flag_map[i].value) {
1295 strcat(str, pkg_state_flag_map[i].str);
1300 str[len-1] = 0; /* squash last comma */
1305 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1310 if (strcmp(str, "ok") == 0) {
1313 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1314 const char *sfname = pkg_state_flag_map[i].str;
1315 int sfname_len = strlen(sfname);
1316 if (strncmp(str, sfname, sfname_len) == 0) {
1317 sf |= pkg_state_flag_map[i].value;
1319 if (str[0] == ',') {
1330 char *pkg_state_status_to_str(pkg_state_status_t ss)
1334 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1335 if (pkg_state_status_map[i].value == ss) {
1336 return xstrdup(pkg_state_status_map[i].str);
1340 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1342 return xstrdup("<STATE_STATUS_UNKNOWN>");
1345 pkg_state_status_t pkg_state_status_from_str(const char *str)
1349 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1350 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1351 return pkg_state_status_map[i].value;
1355 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1357 return SS_NOT_INSTALLED;
1360 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1362 nv_pair_list_elt_t *l;
1364 if (!pkg->architecture)
1367 list_for_each_entry(l , &conf->arch_list.head, node) {
1368 nv_pair_t *nv = (nv_pair_t *)l->data;
1369 if (strcmp(nv->name, pkg->architecture) == 0) {
1370 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1375 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1379 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1381 nv_pair_list_elt_t *l;
1383 list_for_each_entry(l , &conf->arch_list.head, node) {
1384 nv_pair_t *nv = (nv_pair_t *)l->data;
1385 if (strcmp(nv->name, archname) == 0) {
1386 int priority = strtol(nv->value, NULL, 0);
1393 int pkg_info_preinstall_check(opkg_conf_t *conf)
1396 hash_table_t *pkg_hash = &conf->pkg_hash;
1397 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1398 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1400 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1401 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1402 /* update arch_priority for each package */
1403 for (i = 0; i < available_pkgs->len; i++) {
1404 pkg_t *pkg = available_pkgs->pkgs[i];
1405 int arch_priority = 1;
1408 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1409 if (pkg->architecture)
1410 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1412 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1413 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1414 pkg->arch_priority = arch_priority;
1417 for (i = 0; i < available_pkgs->len; i++) {
1418 pkg_t *pkg = available_pkgs->pkgs[i];
1419 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1420 /* clear flags and want for any uninstallable package */
1421 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1422 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1423 pkg->state_want = SW_UNKNOWN;
1424 pkg->state_flag = 0;
1427 pkg_vec_free(available_pkgs);
1429 /* update the file owner data structure */
1430 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1431 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1432 for (i = 0; i < installed_pkgs->len; i++) {
1433 pkg_t *pkg = installed_pkgs->pkgs[i];
1434 str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1435 str_list_elt_t *iter, *niter;
1436 if (installed_files == NULL) {
1437 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1440 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1442 iter = niter, niter = str_list_next(installed_files, iter)) {
1443 char *installed_file = (char *) iter->data;
1444 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1445 file_hash_set_file_owner(conf, installed_file, pkg);
1447 pkg_free_installed_files(pkg);
1449 pkg_vec_free(installed_pkgs);
1454 struct pkg_write_filelist_data {
1460 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1462 struct pkg_write_filelist_data *data = data_;
1463 pkg_t *entry = entry_;
1464 if (entry == data->pkg) {
1465 fprintf(data->stream, "%s\n", key);
1469 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1471 struct pkg_write_filelist_data data;
1472 char *list_file_name = NULL;
1476 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1479 opkg_message(conf, OPKG_INFO,
1480 " creating %s.list file\n", pkg->name);
1481 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1482 if (!list_file_name) {
1483 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1486 opkg_message(conf, OPKG_INFO,
1487 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1488 data.stream = fopen(list_file_name, "w");
1490 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1491 list_file_name, strerror(errno));
1496 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1497 fclose(data.stream);
1498 free(list_file_name);
1500 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1505 int pkg_write_changed_filelists(opkg_conf_t *conf)
1507 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1508 hash_table_t *pkg_hash = &conf->pkg_hash;
1514 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1515 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1516 for (i = 0; i < installed_pkgs->len; i++) {
1517 pkg_t *pkg = installed_pkgs->pkgs[i];
1518 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1519 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1520 err = pkg_write_filelist(conf, pkg);
1522 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1525 pkg_vec_free (installed_pkgs);