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 = calloc(1, sizeof(pkg_t));
84 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
93 int pkg_init(pkg_t *pkg)
101 pkg->architecture = NULL;
102 pkg->maintainer = NULL;
104 pkg->description = NULL;
105 pkg->state_want = SW_UNKNOWN;
106 pkg->state_flag = SF_OK;
107 pkg->state_status = SS_NOT_INSTALLED;
108 pkg->depends_str = NULL;
109 pkg->provides_str = NULL;
110 pkg->depends_count = 0;
112 pkg->suggests_str = NULL;
113 pkg->recommends_str = NULL;
114 pkg->suggests_count = 0;
115 pkg->recommends_count = 0;
117 active_list_init(&pkg->list);
119 /* Abhaya: added init for conflicts fields */
120 pkg->conflicts = NULL;
121 pkg->conflicts_count = 0;
123 /* added for replaces. Jamey 7/23/2002 */
124 pkg->replaces = NULL;
125 pkg->replaces_count = 0;
127 pkg->pre_depends_count = 0;
128 pkg->pre_depends_str = NULL;
129 pkg->provides_count = 0;
130 pkg->provides = NULL;
131 pkg->filename = NULL;
132 pkg->local_filename = NULL;
133 pkg->tmp_unpack_dir = NULL;
135 #if defined HAVE_SHA256
136 pkg->sha256sum = NULL;
139 pkg->installed_size = NULL;
140 pkg->priority = NULL;
142 conffile_list_init(&pkg->conffiles);
143 pkg->installed_files = NULL;
144 pkg->installed_files_ref_cnt = 0;
146 pkg->provided_by_hand = 0;
151 void compound_depend_deinit (compound_depend_t *depends)
154 for (i = 0; i < depends->possibility_count; i++)
157 d = depends->possibilities[i];
161 free (depends->possibilities);
164 void pkg_deinit(pkg_t *pkg)
173 /* revision shares storage with version, so
175 pkg->revision = NULL;
176 /* owned by opkg_conf_t */
178 /* owned by opkg_conf_t */
180 free(pkg->architecture);
181 pkg->architecture = NULL;
182 free(pkg->maintainer);
183 pkg->maintainer = NULL;
186 free(pkg->description);
187 pkg->description = NULL;
188 pkg->state_want = SW_UNKNOWN;
189 pkg->state_flag = SF_OK;
190 pkg->state_status = SS_NOT_INSTALLED;
192 active_list_clear(&pkg->list);
194 free (pkg->replaces);
195 pkg->replaces = NULL;
197 for (i = 0; i < pkg->depends_count; i++)
198 free (pkg->depends_str[i]);
199 free(pkg->depends_str);
200 pkg->depends_str = NULL;
202 for (i = 0; i < pkg->provides_count; i++)
203 free (pkg->provides_str[i]);
204 free(pkg->provides_str);
205 pkg->provides_str = NULL;
207 for (i = 0; i < pkg->conflicts_count; i++)
208 free (pkg->conflicts_str[i]);
209 free(pkg->conflicts_str);
210 pkg->conflicts_str = NULL;
212 for (i = 0; i < pkg->replaces_count; i++)
213 free (pkg->replaces_str[i]);
214 free(pkg->replaces_str);
215 pkg->replaces_str = NULL;
217 for (i = 0; i < pkg->recommends_count; i++)
218 free (pkg->recommends_str[i]);
219 free(pkg->recommends_str);
220 pkg->recommends_str = NULL;
222 for (i = 0; i < pkg->suggests_count; i++)
223 free (pkg->suggests_str[i]);
224 free(pkg->suggests_str);
225 pkg->suggests_str = NULL;
229 int count = pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count;
232 for (x = 0; x < count; x++)
233 compound_depend_deinit (&pkg->depends[x]);
240 for (x = 0; x < pkg->conflicts_count; x++)
241 compound_depend_deinit (&pkg->conflicts[x]);
242 free (pkg->conflicts);
245 free (pkg->provides);
247 pkg->pre_depends_count = 0;
248 free(pkg->pre_depends_str);
249 pkg->pre_depends_str = NULL;
250 pkg->provides_count = 0;
252 pkg->filename = NULL;
253 free(pkg->local_filename);
254 pkg->local_filename = NULL;
255 /* CLEANUP: It'd be nice to pullin the cleanup function from
256 opkg_install.c here. See comment in
257 opkg_install.c:cleanup_temporary_files */
258 free(pkg->tmp_unpack_dir);
259 pkg->tmp_unpack_dir = NULL;
262 #if defined HAVE_SHA256
263 free(pkg->sha256sum);
264 pkg->sha256sum = NULL;
268 free(pkg->installed_size);
269 pkg->installed_size = NULL;
271 pkg->priority = NULL;
274 conffile_list_deinit(&pkg->conffiles);
275 /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
276 since if they are calling deinit, they should know. Maybe do an
277 assertion here instead? */
278 pkg->installed_files_ref_cnt = 1;
279 pkg_free_installed_files(pkg);
285 int pkg_init_from_file(pkg_t *pkg, const char *filename)
288 char **raw, **raw_start;
292 if (err) { return err; }
294 pkg->local_filename = xstrdup(filename);
296 control_file = tmpfile();
297 err = pkg_extract_control_file_to_stream(pkg, control_file);
298 if (err) { return err; }
300 rewind(control_file);
301 raw = raw_start = read_raw_pkgs_from_stream(control_file);
302 pkg_parse_raw(pkg, &raw, NULL, NULL);
304 fclose(control_file);
315 /* Merge any new information in newpkg into oldpkg */
316 /* XXX: CLEANUP: This function shouldn't actually modify anything in
317 newpkg, but should leave it usable. This rework is so that
318 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
320 * uh, i thought that i had originally written this so that it took
321 * two pkgs and returned a new one? we can do that again... -sma
323 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
325 if (oldpkg == newpkg) {
330 oldpkg->src = newpkg->src;
332 oldpkg->dest = newpkg->dest;
333 if (!oldpkg->architecture)
334 oldpkg->architecture = xstrdup(newpkg->architecture);
335 if (!oldpkg->arch_priority)
336 oldpkg->arch_priority = newpkg->arch_priority;
337 if (!oldpkg->section)
338 oldpkg->section = xstrdup(newpkg->section);
339 if(!oldpkg->maintainer)
340 oldpkg->maintainer = xstrdup(newpkg->maintainer);
341 if(!oldpkg->description)
342 oldpkg->description = xstrdup(newpkg->description);
344 /* merge the state_flags from the new package */
345 oldpkg->state_want = newpkg->state_want;
346 oldpkg->state_status = newpkg->state_status;
347 oldpkg->state_flag = newpkg->state_flag;
349 if (oldpkg->state_want == SW_UNKNOWN)
350 oldpkg->state_want = newpkg->state_want;
351 if (oldpkg->state_status == SS_NOT_INSTALLED)
352 oldpkg->state_status = newpkg->state_status;
353 oldpkg->state_flag |= newpkg->state_flag;
356 if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
357 oldpkg->depends_str = newpkg->depends_str;
358 newpkg->depends_str = NULL;
359 oldpkg->depends_count = newpkg->depends_count;
360 newpkg->depends_count = 0;
362 oldpkg->depends = newpkg->depends;
363 newpkg->depends = NULL;
365 oldpkg->pre_depends_str = newpkg->pre_depends_str;
366 newpkg->pre_depends_str = NULL;
367 oldpkg->pre_depends_count = newpkg->pre_depends_count;
368 newpkg->pre_depends_count = 0;
370 oldpkg->recommends_str = newpkg->recommends_str;
371 newpkg->recommends_str = NULL;
372 oldpkg->recommends_count = newpkg->recommends_count;
373 newpkg->recommends_count = 0;
375 oldpkg->suggests_str = newpkg->suggests_str;
376 newpkg->suggests_str = NULL;
377 oldpkg->suggests_count = newpkg->suggests_count;
378 newpkg->suggests_count = 0;
381 if (!oldpkg->provides_str) {
382 oldpkg->provides_str = newpkg->provides_str;
383 newpkg->provides_str = NULL;
384 oldpkg->provides_count = newpkg->provides_count;
385 newpkg->provides_count = 0;
387 oldpkg->provides = newpkg->provides;
388 newpkg->provides = NULL;
391 if (!oldpkg->conflicts_str) {
392 oldpkg->conflicts_str = newpkg->conflicts_str;
393 newpkg->conflicts_str = NULL;
394 oldpkg->conflicts_count = newpkg->conflicts_count;
395 newpkg->conflicts_count = 0;
397 oldpkg->conflicts = newpkg->conflicts;
398 newpkg->conflicts = NULL;
401 if (!oldpkg->replaces_str) {
402 oldpkg->replaces_str = newpkg->replaces_str;
403 newpkg->replaces_str = NULL;
404 oldpkg->replaces_count = newpkg->replaces_count;
405 newpkg->replaces_count = 0;
407 oldpkg->replaces = newpkg->replaces;
408 newpkg->replaces = NULL;
411 if (!oldpkg->filename)
412 oldpkg->filename = xstrdup(newpkg->filename);
414 fprintf(stdout, "pkg=%s old local_filename=%s new local_filename=%s\n",
415 oldpkg->name, oldpkg->local_filename, newpkg->local_filename);
416 if (!oldpkg->local_filename)
417 oldpkg->local_filename = xstrdup(newpkg->local_filename);
418 if (!oldpkg->tmp_unpack_dir)
419 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
421 oldpkg->md5sum = xstrdup(newpkg->md5sum);
422 #if defined HAVE_SHA256
423 if (!oldpkg->sha256sum)
424 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
427 oldpkg->size = xstrdup(newpkg->size);
428 if (!oldpkg->installed_size)
429 oldpkg->installed_size = xstrdup(newpkg->installed_size);
430 if (!oldpkg->priority)
431 oldpkg->priority = xstrdup(newpkg->priority);
433 oldpkg->source = xstrdup(newpkg->source);
434 if (nv_pair_list_empty(&oldpkg->conffiles)){
435 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
436 conffile_list_init(&newpkg->conffiles);
438 if (!oldpkg->installed_files){
439 oldpkg->installed_files = newpkg->installed_files;
440 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
441 newpkg->installed_files = NULL;
443 if (!oldpkg->essential)
444 oldpkg->essential = newpkg->essential;
449 abstract_pkg_t *abstract_pkg_new(void)
451 abstract_pkg_t * ab_pkg;
453 ab_pkg = calloc(1, sizeof(abstract_pkg_t));
455 if (ab_pkg == NULL) {
456 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
460 if ( abstract_pkg_init(ab_pkg) < 0 )
466 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
468 ab_pkg->provided_by = abstract_pkg_vec_alloc();
469 if (ab_pkg->provided_by==NULL){
472 ab_pkg->dependencies_checked = 0;
473 ab_pkg->state_status = SS_NOT_INSTALLED;
478 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
481 char **raw_start=NULL;
483 size_t str_size = strlen(pkg->dest->info_dir)+strlen(pkg->name)+12;
484 temp_str = (char *) alloca (str_size);
485 memset(temp_str, 0 , str_size);
487 if (temp_str == NULL ){
488 opkg_message(conf, OPKG_INFO, "Out of memory in %s\n", __FUNCTION__);
491 sprintf( temp_str,"%s/%s.control",pkg->dest->info_dir,pkg->name);
493 raw = raw_start = read_raw_pkgs_from_file(temp_str);
495 opkg_message(conf, OPKG_ERROR, "Unable to open the control file in %s\n", __FUNCTION__);
500 if (!pkg_valorize_other_field(pkg, &raw ) == 0) {
501 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
516 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
519 int flag_provide_false = 0;
521 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
522 goto UNKNOWN_FMT_FIELD;
529 if (strcasecmp(field, "Architecture") == 0) {
530 if (pkg->architecture) {
531 fprintf(fp, "Architecture: %s\n", pkg->architecture);
533 } else if (strcasecmp(field, "Auto-Installed") == 0) {
534 if (pkg->auto_installed)
535 fprintf(fp, "Auto-Installed: yes\n");
537 goto UNKNOWN_FMT_FIELD;
542 if (strcasecmp(field, "Conffiles") == 0) {
543 conffile_list_elt_t *iter;
545 if (nv_pair_list_empty(&pkg->conffiles))
548 fprintf(fp, "Conffiles:\n");
549 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
550 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
551 fprintf(fp, "%s %s\n",
552 ((conffile_t *)iter->data)->name,
553 ((conffile_t *)iter->data)->value);
556 } else if (strcasecmp(field, "Conflicts") == 0) {
557 if (pkg->conflicts_count) {
558 fprintf(fp, "Conflicts:");
559 for(i = 0; i < pkg->conflicts_count; i++) {
560 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
565 goto UNKNOWN_FMT_FIELD;
570 if (strcasecmp(field, "Depends") == 0) {
571 if (pkg->depends_count) {
572 fprintf(fp, "Depends:");
573 for(i = 0; i < pkg->depends_count; i++) {
574 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
578 } else if (strcasecmp(field, "Description") == 0) {
579 if (pkg->description) {
580 fprintf(fp, "Description: %s\n", pkg->description);
583 goto UNKNOWN_FMT_FIELD;
588 if (pkg->essential) {
589 fprintf(fp, "Essential: yes\n");
595 fprintf(fp, "Filename: %s\n", pkg->filename);
600 if (strcasecmp(field, "Installed-Size") == 0) {
601 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
602 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
603 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
608 if (strcasecmp(field, "Maintainer") == 0) {
609 if (pkg->maintainer) {
610 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
612 } else if (strcasecmp(field, "MD5sum") == 0) {
614 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
617 goto UNKNOWN_FMT_FIELD;
622 if (strcasecmp(field, "Package") == 0) {
623 fprintf(fp, "Package: %s\n", pkg->name);
624 } else if (strcasecmp(field, "Priority") == 0) {
625 fprintf(fp, "Priority: %s\n", pkg->priority);
626 } else if (strcasecmp(field, "Provides") == 0) {
627 if (pkg->provides_count) {
628 /* Here we check if the opkg_internal_use_only is used, and we discard it.*/
629 for ( i=0; i < pkg->provides_count; i++ ){
630 if (strstr(pkg->provides_str[i],"opkg_internal_use_only")!=NULL) {
631 memset (pkg->provides_str[i],'\x0',strlen(pkg->provides_str[i])); /* Pigi clear my trick flag, just in case */
632 flag_provide_false = 1;
635 if ( !flag_provide_false || /* Pigi there is not my trick flag */
636 ((flag_provide_false) && (pkg->provides_count > 1))){ /* Pigi There is, but we also have others Provides */
637 fprintf(fp, "Provides:");
638 for(i = 0; i < pkg->provides_count; i++) {
639 if (strlen(pkg->provides_str[i])>0) {
640 fprintf(fp, "%s %s", i == 1 ? "" : ",", pkg->provides_str[i]);
647 goto UNKNOWN_FMT_FIELD;
652 if (strcasecmp (field, "Replaces") == 0) {
653 if (pkg->replaces_count) {
654 fprintf(fp, "Replaces:");
655 for (i = 0; i < pkg->replaces_count; i++) {
656 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
660 } else if (strcasecmp (field, "Recommends") == 0) {
661 if (pkg->recommends_count) {
662 fprintf(fp, "Recommends:");
663 for(i = 0; i < pkg->recommends_count; i++) {
664 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
669 goto UNKNOWN_FMT_FIELD;
674 if (strcasecmp(field, "Section") == 0) {
676 fprintf(fp, "Section: %s\n", pkg->section);
678 #if defined HAVE_SHA256
679 } else if (strcasecmp(field, "SHA256sum") == 0) {
680 if (pkg->sha256sum) {
681 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
684 } else if (strcasecmp(field, "Size") == 0) {
686 fprintf(fp, "Size: %s\n", pkg->size);
688 } else if (strcasecmp(field, "Source") == 0) {
690 fprintf(fp, "Source: %s\n", pkg->source);
692 } else if (strcasecmp(field, "Status") == 0) {
693 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
694 char *pstat = pkg_state_status_to_str(pkg->state_status);
695 char *pwant = pkg_state_want_to_str(pkg->state_want);
697 if (pflag == NULL || pstat == NULL || pwant == NULL)
700 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
705 } else if (strcasecmp(field, "Suggests") == 0) {
706 if (pkg->suggests_count) {
707 fprintf(fp, "Suggests:");
708 for(i = 0; i < pkg->suggests_count; i++) {
709 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
714 goto UNKNOWN_FMT_FIELD;
719 if (strcasecmp(field, "Tags") == 0) {
721 fprintf(fp, "Tags: %s\n", pkg->tags);
728 char *version = pkg_version_str_alloc(pkg);
731 fprintf(fp, "Version: %s\n", version);
736 goto UNKNOWN_FMT_FIELD;
742 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
745 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
747 pkg_formatted_field(fp, pkg, "Package");
748 pkg_formatted_field(fp, pkg, "Version");
749 pkg_formatted_field(fp, pkg, "Depends");
750 pkg_formatted_field(fp, pkg, "Recommends");
751 pkg_formatted_field(fp, pkg, "Suggests");
752 pkg_formatted_field(fp, pkg, "Provides");
753 pkg_formatted_field(fp, pkg, "Replaces");
754 pkg_formatted_field(fp, pkg, "Conflicts");
755 pkg_formatted_field(fp, pkg, "Status");
756 pkg_formatted_field(fp, pkg, "Section");
757 pkg_formatted_field(fp, pkg, "Essential");
758 pkg_formatted_field(fp, pkg, "Architecture");
759 pkg_formatted_field(fp, pkg, "Maintainer");
760 pkg_formatted_field(fp, pkg, "MD5sum");
761 pkg_formatted_field(fp, pkg, "Size");
762 pkg_formatted_field(fp, pkg, "Filename");
763 pkg_formatted_field(fp, pkg, "Conffiles");
764 pkg_formatted_field(fp, pkg, "Source");
765 pkg_formatted_field(fp, pkg, "Description");
766 pkg_formatted_field(fp, pkg, "Installed-Time");
767 pkg_formatted_field(fp, pkg, "Tags");
771 void pkg_print_status(pkg_t * pkg, FILE * file)
777 /* XXX: QUESTION: Do we actually want more fields here? The
778 original idea was to save space by installing only what was
779 needed for actual computation, (package, version, status,
780 essential, conffiles). The assumption is that all other fields
781 can be found in th available file.
783 But, someone proposed the idea to make it possible to
784 reconstruct a .opk from an installed package, (ie. for beaming
785 from one handheld to another). So, maybe we actually want a few
786 more fields here, (depends, suggests, etc.), so that that would
787 be guaranteed to work even in the absence of more information
788 from the available file.
790 28-MAR-03: kergoth and I discussed this yesterday. We think
791 the essential info needs to be here for all installed packages
792 because they may not appear in the Packages files on various
793 feeds. Furthermore, one should be able to install from URL or
794 local storage without requiring a Packages file from any feed.
797 pkg_formatted_field(file, pkg, "Package");
798 pkg_formatted_field(file, pkg, "Version");
799 pkg_formatted_field(file, pkg, "Depends");
800 pkg_formatted_field(file, pkg, "Recommends");
801 pkg_formatted_field(file, pkg, "Suggests");
802 pkg_formatted_field(file, pkg, "Provides");
803 pkg_formatted_field(file, pkg, "Replaces");
804 pkg_formatted_field(file, pkg, "Conflicts");
805 pkg_formatted_field(file, pkg, "Status");
806 pkg_formatted_field(file, pkg, "Essential");
807 pkg_formatted_field(file, pkg, "Architecture");
808 pkg_formatted_field(file, pkg, "Conffiles");
809 pkg_formatted_field(file, pkg, "Installed-Time");
810 pkg_formatted_field(file, pkg, "Auto-Installed");
815 * libdpkg - Debian packaging suite library routines
816 * vercmp.c - comparison of version numbers
818 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
820 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
824 if (pkg->epoch > ref_pkg->epoch) {
828 if (pkg->epoch < ref_pkg->epoch) {
832 r = verrevcmp(pkg->version, ref_pkg->version);
837 r = verrevcmp(pkg->revision, ref_pkg->revision);
845 /* assume ascii; warning: evaluates x multiple times! */
846 #define order(x) ((x) == '~' ? -1 \
849 : isalpha((x)) ? (x) \
852 static int verrevcmp(const char *val, const char *ref) {
856 while (*val || *ref) {
859 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
860 int vc= order(*val), rc= order(*ref);
861 if (vc != rc) return vc - rc;
865 while ( *val == '0' ) val++;
866 while ( *ref == '0' ) ref++;
867 while (isdigit(*val) && isdigit(*ref)) {
868 if (!first_diff) first_diff= *val - *ref;
871 if (isdigit(*val)) return 1;
872 if (isdigit(*ref)) return -1;
873 if (first_diff) return first_diff;
878 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
882 r = pkg_compare_versions(it, ref);
884 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
888 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
892 if (strcmp(op, "<<") == 0) {
896 if (strcmp(op, ">>") == 0) {
900 if (strcmp(op, "=") == 0) {
904 fprintf(stderr, "unknown operator: %s", op);
908 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
910 const pkg_t *a = *(const pkg_t**) p1;
911 const pkg_t *b = *(const pkg_t**) p2;
914 if (!a->name || !b->name) {
915 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
916 a, a->name, b, b->name);
920 namecmp = strcmp(a->name, b->name);
923 vercmp = pkg_compare_versions(a, b);
926 if (!a->arch_priority || !b->arch_priority) {
927 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
928 a, a->arch_priority, b, b->arch_priority);
931 if (a->arch_priority > b->arch_priority)
933 if (a->arch_priority < b->arch_priority)
938 int abstract_pkg_name_compare(const void *p1, const void *p2)
940 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
941 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
942 if (!a->name || !b->name) {
943 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
944 a, a->name, b, b->name);
947 return strcmp(a->name, b->name);
951 char *pkg_version_str_alloc(pkg_t *pkg)
953 char *complete_version;
958 sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
960 epoch_str = xstrdup("");
963 if (pkg->revision && strlen(pkg->revision)) {
964 sprintf_alloc(&revision_str, "-%s", pkg->revision);
966 revision_str = xstrdup("");
970 sprintf_alloc(&complete_version, "%s%s%s",
971 epoch_str, pkg->version, revision_str);
976 return complete_version;
979 str_list_t *pkg_get_installed_files(pkg_t *pkg)
982 char *list_file_name = NULL;
983 FILE *list_file = NULL;
985 char *installed_file_name;
988 pkg->installed_files_ref_cnt++;
990 if (pkg->installed_files) {
991 return pkg->installed_files;
994 pkg->installed_files = str_list_alloc();
995 if (pkg->installed_files == NULL) {
996 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1000 /* For uninstalled packages, get the file list directly from the package.
1001 For installed packages, look at the package.list file in the database.
1003 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
1004 if (pkg->local_filename == NULL) {
1005 return pkg->installed_files;
1007 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1008 file. In other words, change deb_extract so that it can
1009 simply return the file list as a char *[] rather than
1010 insisting on writing in to a FILE * as it does now. */
1011 list_file = tmpfile();
1012 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1015 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1016 __FUNCTION__, pkg->local_filename, strerror(err));
1017 return pkg->installed_files;
1021 sprintf_alloc(&list_file_name, "%s/%s.list",
1022 pkg->dest->info_dir, pkg->name);
1023 if (! file_exists(list_file_name)) {
1024 free(list_file_name);
1025 return pkg->installed_files;
1028 list_file = fopen(list_file_name, "r");
1029 if (list_file == NULL) {
1030 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1031 list_file_name, strerror(errno));
1032 free(list_file_name);
1033 return pkg->installed_files;
1035 free(list_file_name);
1038 rootdirlen = strlen( pkg->dest->root_dir );
1042 line = file_read_line_alloc(list_file);
1049 /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1050 if( strncmp( pkg->dest->root_dir,
1053 if (*file_name == '.') {
1056 if (*file_name == '/') {
1060 /* Freed in pkg_free_installed_files */
1061 sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1063 // already contains root_dir as header -> ABSOLUTE
1064 sprintf_alloc(&installed_file_name, "%s", file_name);
1066 str_list_append(pkg->installed_files, installed_file_name);
1067 free(installed_file_name);
1073 return pkg->installed_files;
1076 /* XXX: CLEANUP: This function and it's counterpart,
1077 (pkg_get_installed_files), do not match our init/deinit naming
1078 convention. Nor the alloc/free convention. But, then again, neither
1079 of these conventions currrently fit the way these two functions
1081 int pkg_free_installed_files(pkg_t *pkg)
1083 pkg->installed_files_ref_cnt--;
1085 if (pkg->installed_files_ref_cnt > 0)
1088 if (pkg->installed_files) {
1089 str_list_purge(pkg->installed_files);
1092 pkg->installed_files = NULL;
1097 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1100 char *list_file_name;
1102 //I don't think pkg_free_installed_files should be called here. Jamey
1103 //pkg_free_installed_files(pkg);
1105 sprintf_alloc(&list_file_name, "%s/%s.list",
1106 pkg->dest->info_dir, pkg->name);
1107 if (!conf->noaction) {
1108 err = unlink(list_file_name);
1109 free(list_file_name);
1118 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1120 conffile_list_elt_t *iter;
1121 conffile_t *conffile;
1127 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1128 conffile = (conffile_t *)iter->data;
1130 if (strcmp(conffile->name, file_name) == 0) {
1138 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1139 const char *script, const char *args)
1148 /* XXX: CLEANUP: There must be a better way to handle maintainer
1149 scripts when running with offline_root mode and/or a dest other
1150 than '/'. I've been playing around with some clever chroot
1151 tricks and I might come up with something workable. */
1153 * Attempt to provide a restricted environment for offline operation
1154 * Need the following set as a minimum:
1155 * OPKG_OFFLINE_ROOT = absolute path to root dir
1156 * D = absolute path to root dir (for OE generated postinst)
1157 * PATH = something safe (a restricted set of utilities)
1160 if (conf->offline_root) {
1161 if (conf->offline_root_path) {
1162 setenv("PATH", conf->offline_root_path, 1);
1164 opkg_message(conf, OPKG_NOTICE,
1165 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1168 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1169 setenv("D", conf->offline_root, 1);
1172 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1173 maintainer script within a chroot environment. */
1175 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1176 have scripts in pkg->tmp_unpack_dir. */
1177 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1178 if (pkg->dest == NULL) {
1179 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1180 __FUNCTION__, pkg->name);
1183 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1185 if (pkg->tmp_unpack_dir == NULL) {
1186 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1187 __FUNCTION__, pkg->name);
1190 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1193 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1196 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1198 if (! file_exists(path)) {
1203 sprintf_alloc(&cmd, "%s %s", path, args);
1210 fprintf(stderr, "%s script returned status %d\n", script, err);
1217 char *pkg_state_want_to_str(pkg_state_want_t sw)
1221 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1222 if (pkg_state_want_map[i].value == sw) {
1223 return xstrdup(pkg_state_want_map[i].str);
1227 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1229 return xstrdup("<STATE_WANT_UNKNOWN>");
1232 pkg_state_want_t pkg_state_want_from_str(char *str)
1236 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1237 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1238 return pkg_state_want_map[i].value;
1242 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1247 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1250 int len = 3; /* ok\000 is minimum */
1253 /* clear the temporary flags before converting to string */
1254 sf &= SF_NONVOLATILE_FLAGS;
1257 return xstrdup("ok");
1260 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1261 if (sf & pkg_state_flag_map[i].value) {
1262 len += strlen(pkg_state_flag_map[i].str) + 1;
1266 if ( str == NULL ) {
1267 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
1271 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1272 if (sf & pkg_state_flag_map[i].value) {
1273 strcat(str, pkg_state_flag_map[i].str);
1278 str[len-1] = 0; /* squash last comma */
1283 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1288 if (strcmp(str, "ok") == 0) {
1291 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1292 const char *sfname = pkg_state_flag_map[i].str;
1293 int sfname_len = strlen(sfname);
1294 if (strncmp(str, sfname, sfname_len) == 0) {
1295 sf |= pkg_state_flag_map[i].value;
1297 if (str[0] == ',') {
1308 char *pkg_state_status_to_str(pkg_state_status_t ss)
1312 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1313 if (pkg_state_status_map[i].value == ss) {
1314 return xstrdup(pkg_state_status_map[i].str);
1318 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1320 return xstrdup("<STATE_STATUS_UNKNOWN>");
1323 pkg_state_status_t pkg_state_status_from_str(const char *str)
1327 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1328 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1329 return pkg_state_status_map[i].value;
1333 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1335 return SS_NOT_INSTALLED;
1338 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1340 nv_pair_list_elt_t *l;
1342 if (!pkg->architecture)
1345 list_for_each_entry(l , &conf->arch_list.head, node) {
1346 nv_pair_t *nv = (nv_pair_t *)l->data;
1347 if (strcmp(nv->name, pkg->architecture) == 0) {
1348 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1353 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1357 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1359 nv_pair_list_elt_t *l;
1361 list_for_each_entry(l , &conf->arch_list.head, node) {
1362 nv_pair_t *nv = (nv_pair_t *)l->data;
1363 if (strcmp(nv->name, archname) == 0) {
1364 int priority = strtol(nv->value, NULL, 0);
1371 int pkg_info_preinstall_check(opkg_conf_t *conf)
1374 hash_table_t *pkg_hash = &conf->pkg_hash;
1375 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1376 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1378 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1379 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1380 /* update arch_priority for each package */
1381 for (i = 0; i < available_pkgs->len; i++) {
1382 pkg_t *pkg = available_pkgs->pkgs[i];
1383 int arch_priority = 1;
1386 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1387 if (pkg->architecture)
1388 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1390 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1391 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1392 pkg->arch_priority = arch_priority;
1395 for (i = 0; i < available_pkgs->len; i++) {
1396 pkg_t *pkg = available_pkgs->pkgs[i];
1397 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1398 /* clear flags and want for any uninstallable package */
1399 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1400 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1401 pkg->state_want = SW_UNKNOWN;
1402 pkg->state_flag = 0;
1405 pkg_vec_free(available_pkgs);
1407 /* update the file owner data structure */
1408 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1409 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1410 for (i = 0; i < installed_pkgs->len; i++) {
1411 pkg_t *pkg = installed_pkgs->pkgs[i];
1412 str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1413 str_list_elt_t *iter, *niter;
1414 if (installed_files == NULL) {
1415 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1418 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1420 iter = niter, niter = str_list_next(installed_files, iter)) {
1421 char *installed_file = (char *) iter->data;
1422 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1423 file_hash_set_file_owner(conf, installed_file, pkg);
1425 pkg_free_installed_files(pkg);
1427 pkg_vec_free(installed_pkgs);
1432 struct pkg_write_filelist_data {
1438 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1440 struct pkg_write_filelist_data *data = data_;
1441 pkg_t *entry = entry_;
1442 if (entry == data->pkg) {
1443 fprintf(data->stream, "%s\n", key);
1447 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1449 struct pkg_write_filelist_data data;
1450 char *list_file_name = NULL;
1454 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1457 opkg_message(conf, OPKG_INFO,
1458 " creating %s.list file\n", pkg->name);
1459 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1460 if (!list_file_name) {
1461 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1464 opkg_message(conf, OPKG_INFO,
1465 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1466 data.stream = fopen(list_file_name, "w");
1468 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1469 list_file_name, strerror(errno));
1474 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1475 fclose(data.stream);
1476 free(list_file_name);
1478 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1483 int pkg_write_changed_filelists(opkg_conf_t *conf)
1485 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1486 hash_table_t *pkg_hash = &conf->pkg_hash;
1492 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1493 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1494 for (i = 0; i < installed_pkgs->len; i++) {
1495 pkg_t *pkg = installed_pkgs->pkgs[i];
1496 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1497 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1498 err = pkg_write_filelist(conf, pkg);
1500 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1503 pkg_vec_free (installed_pkgs);