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));
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);
413 if (!oldpkg->local_filename)
414 oldpkg->local_filename = xstrdup(newpkg->local_filename);
415 if (!oldpkg->tmp_unpack_dir)
416 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
418 oldpkg->md5sum = xstrdup(newpkg->md5sum);
419 #if defined HAVE_SHA256
420 if (!oldpkg->sha256sum)
421 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
424 oldpkg->size = xstrdup(newpkg->size);
425 if (!oldpkg->installed_size)
426 oldpkg->installed_size = xstrdup(newpkg->installed_size);
427 if (!oldpkg->priority)
428 oldpkg->priority = xstrdup(newpkg->priority);
430 oldpkg->source = xstrdup(newpkg->source);
431 if (nv_pair_list_empty(&oldpkg->conffiles)){
432 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
433 conffile_list_init(&newpkg->conffiles);
435 if (!oldpkg->installed_files){
436 oldpkg->installed_files = newpkg->installed_files;
437 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
438 newpkg->installed_files = NULL;
440 if (!oldpkg->essential)
441 oldpkg->essential = newpkg->essential;
446 abstract_pkg_t *abstract_pkg_new(void)
448 abstract_pkg_t * ab_pkg;
450 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
452 if (ab_pkg == NULL) {
453 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
457 if ( abstract_pkg_init(ab_pkg) < 0 )
463 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
465 ab_pkg->provided_by = abstract_pkg_vec_alloc();
466 if (ab_pkg->provided_by==NULL){
469 ab_pkg->dependencies_checked = 0;
470 ab_pkg->state_status = SS_NOT_INSTALLED;
475 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
478 char **raw_start=NULL;
480 size_t str_size = strlen(pkg->dest->info_dir)+strlen(pkg->name)+12;
481 temp_str = (char *) alloca (str_size);
482 memset(temp_str, 0 , str_size);
484 if (temp_str == NULL ){
485 opkg_message(conf, OPKG_INFO, "Out of memory in %s\n", __FUNCTION__);
488 sprintf( temp_str,"%s/%s.control",pkg->dest->info_dir,pkg->name);
490 raw = raw_start = read_raw_pkgs_from_file(temp_str);
492 opkg_message(conf, OPKG_ERROR, "Unable to open the control file in %s\n", __FUNCTION__);
497 if (!pkg_valorize_other_field(pkg, &raw ) == 0) {
498 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
513 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
516 int flag_provide_false = 0;
518 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
519 goto UNKNOWN_FMT_FIELD;
526 if (strcasecmp(field, "Architecture") == 0) {
527 if (pkg->architecture) {
528 fprintf(fp, "Architecture: %s\n", pkg->architecture);
530 } else if (strcasecmp(field, "Auto-Installed") == 0) {
531 if (pkg->auto_installed)
532 fprintf(fp, "Auto-Installed: yes\n");
534 goto UNKNOWN_FMT_FIELD;
539 if (strcasecmp(field, "Conffiles") == 0) {
540 conffile_list_elt_t *iter;
542 if (nv_pair_list_empty(&pkg->conffiles))
545 fprintf(fp, "Conffiles:\n");
546 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
547 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
548 fprintf(fp, "%s %s\n",
549 ((conffile_t *)iter->data)->name,
550 ((conffile_t *)iter->data)->value);
553 } else if (strcasecmp(field, "Conflicts") == 0) {
554 if (pkg->conflicts_count) {
555 fprintf(fp, "Conflicts:");
556 for(i = 0; i < pkg->conflicts_count; i++) {
557 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
562 goto UNKNOWN_FMT_FIELD;
567 if (strcasecmp(field, "Depends") == 0) {
568 if (pkg->depends_count) {
569 fprintf(fp, "Depends:");
570 for(i = 0; i < pkg->depends_count; i++) {
571 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
575 } else if (strcasecmp(field, "Description") == 0) {
576 if (pkg->description) {
577 fprintf(fp, "Description: %s\n", pkg->description);
580 goto UNKNOWN_FMT_FIELD;
585 if (pkg->essential) {
586 fprintf(fp, "Essential: yes\n");
592 fprintf(fp, "Filename: %s\n", pkg->filename);
597 if (strcasecmp(field, "Installed-Size") == 0) {
598 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
599 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
600 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
605 if (strcasecmp(field, "Maintainer") == 0) {
606 if (pkg->maintainer) {
607 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
609 } else if (strcasecmp(field, "MD5sum") == 0) {
611 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
614 goto UNKNOWN_FMT_FIELD;
619 if (strcasecmp(field, "Package") == 0) {
620 fprintf(fp, "Package: %s\n", pkg->name);
621 } else if (strcasecmp(field, "Priority") == 0) {
622 fprintf(fp, "Priority: %s\n", pkg->priority);
623 } else if (strcasecmp(field, "Provides") == 0) {
624 if (pkg->provides_count) {
625 /* Here we check if the opkg_internal_use_only is used, and we discard it.*/
626 for ( i=0; i < pkg->provides_count; i++ ){
627 if (strstr(pkg->provides_str[i],"opkg_internal_use_only")!=NULL) {
628 memset (pkg->provides_str[i],'\x0',strlen(pkg->provides_str[i])); /* Pigi clear my trick flag, just in case */
629 flag_provide_false = 1;
632 if ( !flag_provide_false || /* Pigi there is not my trick flag */
633 ((flag_provide_false) && (pkg->provides_count > 1))){ /* Pigi There is, but we also have others Provides */
634 fprintf(fp, "Provides:");
635 for(i = 0; i < pkg->provides_count; i++) {
636 if (strlen(pkg->provides_str[i])>0) {
637 fprintf(fp, "%s %s", i == 1 ? "" : ",", pkg->provides_str[i]);
644 goto UNKNOWN_FMT_FIELD;
649 if (strcasecmp (field, "Replaces") == 0) {
650 if (pkg->replaces_count) {
651 fprintf(fp, "Replaces:");
652 for (i = 0; i < pkg->replaces_count; i++) {
653 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
657 } else if (strcasecmp (field, "Recommends") == 0) {
658 if (pkg->recommends_count) {
659 fprintf(fp, "Recommends:");
660 for(i = 0; i < pkg->recommends_count; i++) {
661 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
666 goto UNKNOWN_FMT_FIELD;
671 if (strcasecmp(field, "Section") == 0) {
673 fprintf(fp, "Section: %s\n", pkg->section);
675 #if defined HAVE_SHA256
676 } else if (strcasecmp(field, "SHA256sum") == 0) {
677 if (pkg->sha256sum) {
678 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
681 } else if (strcasecmp(field, "Size") == 0) {
683 fprintf(fp, "Size: %s\n", pkg->size);
685 } else if (strcasecmp(field, "Source") == 0) {
687 fprintf(fp, "Source: %s\n", pkg->source);
689 } else if (strcasecmp(field, "Status") == 0) {
690 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
691 char *pstat = pkg_state_status_to_str(pkg->state_status);
692 char *pwant = pkg_state_want_to_str(pkg->state_want);
694 if (pflag == NULL || pstat == NULL || pwant == NULL)
697 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
702 } else if (strcasecmp(field, "Suggests") == 0) {
703 if (pkg->suggests_count) {
704 fprintf(fp, "Suggests:");
705 for(i = 0; i < pkg->suggests_count; i++) {
706 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
711 goto UNKNOWN_FMT_FIELD;
716 if (strcasecmp(field, "Tags") == 0) {
718 fprintf(fp, "Tags: %s\n", pkg->tags);
725 char *version = pkg_version_str_alloc(pkg);
728 fprintf(fp, "Version: %s\n", version);
733 goto UNKNOWN_FMT_FIELD;
739 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
742 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
744 pkg_formatted_field(fp, pkg, "Package");
745 pkg_formatted_field(fp, pkg, "Version");
746 pkg_formatted_field(fp, pkg, "Depends");
747 pkg_formatted_field(fp, pkg, "Recommends");
748 pkg_formatted_field(fp, pkg, "Suggests");
749 pkg_formatted_field(fp, pkg, "Provides");
750 pkg_formatted_field(fp, pkg, "Replaces");
751 pkg_formatted_field(fp, pkg, "Conflicts");
752 pkg_formatted_field(fp, pkg, "Status");
753 pkg_formatted_field(fp, pkg, "Section");
754 pkg_formatted_field(fp, pkg, "Essential");
755 pkg_formatted_field(fp, pkg, "Architecture");
756 pkg_formatted_field(fp, pkg, "Maintainer");
757 pkg_formatted_field(fp, pkg, "MD5sum");
758 pkg_formatted_field(fp, pkg, "Size");
759 pkg_formatted_field(fp, pkg, "Filename");
760 pkg_formatted_field(fp, pkg, "Conffiles");
761 pkg_formatted_field(fp, pkg, "Source");
762 pkg_formatted_field(fp, pkg, "Description");
763 pkg_formatted_field(fp, pkg, "Installed-Time");
764 pkg_formatted_field(fp, pkg, "Tags");
768 void pkg_print_status(pkg_t * pkg, FILE * file)
774 /* XXX: QUESTION: Do we actually want more fields here? The
775 original idea was to save space by installing only what was
776 needed for actual computation, (package, version, status,
777 essential, conffiles). The assumption is that all other fields
778 can be found in th available file.
780 But, someone proposed the idea to make it possible to
781 reconstruct a .opk from an installed package, (ie. for beaming
782 from one handheld to another). So, maybe we actually want a few
783 more fields here, (depends, suggests, etc.), so that that would
784 be guaranteed to work even in the absence of more information
785 from the available file.
787 28-MAR-03: kergoth and I discussed this yesterday. We think
788 the essential info needs to be here for all installed packages
789 because they may not appear in the Packages files on various
790 feeds. Furthermore, one should be able to install from URL or
791 local storage without requiring a Packages file from any feed.
794 pkg_formatted_field(file, pkg, "Package");
795 pkg_formatted_field(file, pkg, "Version");
796 pkg_formatted_field(file, pkg, "Depends");
797 pkg_formatted_field(file, pkg, "Recommends");
798 pkg_formatted_field(file, pkg, "Suggests");
799 pkg_formatted_field(file, pkg, "Provides");
800 pkg_formatted_field(file, pkg, "Replaces");
801 pkg_formatted_field(file, pkg, "Conflicts");
802 pkg_formatted_field(file, pkg, "Status");
803 pkg_formatted_field(file, pkg, "Essential");
804 pkg_formatted_field(file, pkg, "Architecture");
805 pkg_formatted_field(file, pkg, "Conffiles");
806 pkg_formatted_field(file, pkg, "Installed-Time");
807 pkg_formatted_field(file, pkg, "Auto-Installed");
812 * libdpkg - Debian packaging suite library routines
813 * vercmp.c - comparison of version numbers
815 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
817 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
821 if (pkg->epoch > ref_pkg->epoch) {
825 if (pkg->epoch < ref_pkg->epoch) {
829 r = verrevcmp(pkg->version, ref_pkg->version);
834 r = verrevcmp(pkg->revision, ref_pkg->revision);
842 /* assume ascii; warning: evaluates x multiple times! */
843 #define order(x) ((x) == '~' ? -1 \
846 : isalpha((x)) ? (x) \
849 static int verrevcmp(const char *val, const char *ref) {
853 while (*val || *ref) {
856 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
857 int vc= order(*val), rc= order(*ref);
858 if (vc != rc) return vc - rc;
862 while ( *val == '0' ) val++;
863 while ( *ref == '0' ) ref++;
864 while (isdigit(*val) && isdigit(*ref)) {
865 if (!first_diff) first_diff= *val - *ref;
868 if (isdigit(*val)) return 1;
869 if (isdigit(*ref)) return -1;
870 if (first_diff) return first_diff;
875 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
879 r = pkg_compare_versions(it, ref);
881 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
885 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
889 if (strcmp(op, "<<") == 0) {
893 if (strcmp(op, ">>") == 0) {
897 if (strcmp(op, "=") == 0) {
901 fprintf(stderr, "unknown operator: %s", op);
905 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
907 const pkg_t *a = *(const pkg_t**) p1;
908 const pkg_t *b = *(const pkg_t**) p2;
911 if (!a->name || !b->name) {
912 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
913 a, a->name, b, b->name);
917 namecmp = strcmp(a->name, b->name);
920 vercmp = pkg_compare_versions(a, b);
923 if (!a->arch_priority || !b->arch_priority) {
924 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
925 a, a->arch_priority, b, b->arch_priority);
928 if (a->arch_priority > b->arch_priority)
930 if (a->arch_priority < b->arch_priority)
935 int abstract_pkg_name_compare(const void *p1, const void *p2)
937 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
938 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
939 if (!a->name || !b->name) {
940 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
941 a, a->name, b, b->name);
944 return strcmp(a->name, b->name);
948 char *pkg_version_str_alloc(pkg_t *pkg)
950 char *complete_version;
955 sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
957 epoch_str = xstrdup("");
960 if (pkg->revision && strlen(pkg->revision)) {
961 sprintf_alloc(&revision_str, "-%s", pkg->revision);
963 revision_str = xstrdup("");
967 sprintf_alloc(&complete_version, "%s%s%s",
968 epoch_str, pkg->version, revision_str);
973 return complete_version;
976 str_list_t *pkg_get_installed_files(pkg_t *pkg)
979 char *list_file_name = NULL;
980 FILE *list_file = NULL;
982 char *installed_file_name;
985 pkg->installed_files_ref_cnt++;
987 if (pkg->installed_files) {
988 return pkg->installed_files;
991 pkg->installed_files = str_list_alloc();
993 /* For uninstalled packages, get the file list directly from the package.
994 For installed packages, look at the package.list file in the database.
996 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
997 if (pkg->local_filename == NULL) {
998 return pkg->installed_files;
1000 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
1001 file. In other words, change deb_extract so that it can
1002 simply return the file list as a char *[] rather than
1003 insisting on writing in to a FILE * as it does now. */
1004 list_file = tmpfile();
1005 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1008 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1009 __FUNCTION__, pkg->local_filename, strerror(err));
1010 return pkg->installed_files;
1014 sprintf_alloc(&list_file_name, "%s/%s.list",
1015 pkg->dest->info_dir, pkg->name);
1016 if (! file_exists(list_file_name)) {
1017 free(list_file_name);
1018 return pkg->installed_files;
1021 list_file = fopen(list_file_name, "r");
1022 if (list_file == NULL) {
1023 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1024 list_file_name, strerror(errno));
1025 free(list_file_name);
1026 return pkg->installed_files;
1028 free(list_file_name);
1031 rootdirlen = strlen( pkg->dest->root_dir );
1035 line = file_read_line_alloc(list_file);
1042 /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1043 if( strncmp( pkg->dest->root_dir,
1046 if (*file_name == '.') {
1049 if (*file_name == '/') {
1053 /* Freed in pkg_free_installed_files */
1054 sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1056 // already contains root_dir as header -> ABSOLUTE
1057 sprintf_alloc(&installed_file_name, "%s", file_name);
1059 str_list_append(pkg->installed_files, installed_file_name);
1060 free(installed_file_name);
1066 return pkg->installed_files;
1069 /* XXX: CLEANUP: This function and it's counterpart,
1070 (pkg_get_installed_files), do not match our init/deinit naming
1071 convention. Nor the alloc/free convention. But, then again, neither
1072 of these conventions currrently fit the way these two functions
1074 int pkg_free_installed_files(pkg_t *pkg)
1076 pkg->installed_files_ref_cnt--;
1078 if (pkg->installed_files_ref_cnt > 0)
1081 if (pkg->installed_files) {
1082 str_list_purge(pkg->installed_files);
1085 pkg->installed_files = NULL;
1090 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1093 char *list_file_name;
1095 //I don't think pkg_free_installed_files should be called here. Jamey
1096 //pkg_free_installed_files(pkg);
1098 sprintf_alloc(&list_file_name, "%s/%s.list",
1099 pkg->dest->info_dir, pkg->name);
1100 if (!conf->noaction) {
1101 err = unlink(list_file_name);
1102 free(list_file_name);
1111 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1113 conffile_list_elt_t *iter;
1114 conffile_t *conffile;
1120 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1121 conffile = (conffile_t *)iter->data;
1123 if (strcmp(conffile->name, file_name) == 0) {
1131 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1132 const char *script, const char *args)
1141 /* XXX: CLEANUP: There must be a better way to handle maintainer
1142 scripts when running with offline_root mode and/or a dest other
1143 than '/'. I've been playing around with some clever chroot
1144 tricks and I might come up with something workable. */
1146 * Attempt to provide a restricted environment for offline operation
1147 * Need the following set as a minimum:
1148 * OPKG_OFFLINE_ROOT = absolute path to root dir
1149 * D = absolute path to root dir (for OE generated postinst)
1150 * PATH = something safe (a restricted set of utilities)
1153 if (conf->offline_root) {
1154 if (conf->offline_root_path) {
1155 setenv("PATH", conf->offline_root_path, 1);
1157 opkg_message(conf, OPKG_NOTICE,
1158 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1161 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1162 setenv("D", conf->offline_root, 1);
1165 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1166 maintainer script within a chroot environment. */
1168 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1169 have scripts in pkg->tmp_unpack_dir. */
1170 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1171 if (pkg->dest == NULL) {
1172 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1173 __FUNCTION__, pkg->name);
1176 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1178 if (pkg->tmp_unpack_dir == NULL) {
1179 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1180 __FUNCTION__, pkg->name);
1183 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1186 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1189 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1191 if (! file_exists(path)) {
1196 sprintf_alloc(&cmd, "%s %s", path, args);
1203 fprintf(stderr, "%s script returned status %d\n", script, err);
1210 char *pkg_state_want_to_str(pkg_state_want_t sw)
1214 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1215 if (pkg_state_want_map[i].value == sw) {
1216 return xstrdup(pkg_state_want_map[i].str);
1220 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1222 return xstrdup("<STATE_WANT_UNKNOWN>");
1225 pkg_state_want_t pkg_state_want_from_str(char *str)
1229 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1230 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1231 return pkg_state_want_map[i].value;
1235 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1240 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1243 int len = 3; /* ok\000 is minimum */
1246 /* clear the temporary flags before converting to string */
1247 sf &= SF_NONVOLATILE_FLAGS;
1250 return xstrdup("ok");
1253 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1254 if (sf & pkg_state_flag_map[i].value) {
1255 len += strlen(pkg_state_flag_map[i].str) + 1;
1260 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1261 if (sf & pkg_state_flag_map[i].value) {
1262 strcat(str, pkg_state_flag_map[i].str);
1267 str[len-1] = 0; /* squash last comma */
1272 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1277 if (strcmp(str, "ok") == 0) {
1280 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1281 const char *sfname = pkg_state_flag_map[i].str;
1282 int sfname_len = strlen(sfname);
1283 if (strncmp(str, sfname, sfname_len) == 0) {
1284 sf |= pkg_state_flag_map[i].value;
1286 if (str[0] == ',') {
1297 char *pkg_state_status_to_str(pkg_state_status_t ss)
1301 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1302 if (pkg_state_status_map[i].value == ss) {
1303 return xstrdup(pkg_state_status_map[i].str);
1307 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1309 return xstrdup("<STATE_STATUS_UNKNOWN>");
1312 pkg_state_status_t pkg_state_status_from_str(const char *str)
1316 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1317 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1318 return pkg_state_status_map[i].value;
1322 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1324 return SS_NOT_INSTALLED;
1327 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1329 nv_pair_list_elt_t *l;
1331 if (!pkg->architecture)
1334 list_for_each_entry(l , &conf->arch_list.head, node) {
1335 nv_pair_t *nv = (nv_pair_t *)l->data;
1336 if (strcmp(nv->name, pkg->architecture) == 0) {
1337 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1342 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1346 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1348 nv_pair_list_elt_t *l;
1350 list_for_each_entry(l , &conf->arch_list.head, node) {
1351 nv_pair_t *nv = (nv_pair_t *)l->data;
1352 if (strcmp(nv->name, archname) == 0) {
1353 int priority = strtol(nv->value, NULL, 0);
1360 int pkg_info_preinstall_check(opkg_conf_t *conf)
1363 hash_table_t *pkg_hash = &conf->pkg_hash;
1364 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1365 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1367 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1368 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1369 /* update arch_priority for each package */
1370 for (i = 0; i < available_pkgs->len; i++) {
1371 pkg_t *pkg = available_pkgs->pkgs[i];
1372 int arch_priority = 1;
1375 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1376 if (pkg->architecture)
1377 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1379 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1380 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1381 pkg->arch_priority = arch_priority;
1384 for (i = 0; i < available_pkgs->len; i++) {
1385 pkg_t *pkg = available_pkgs->pkgs[i];
1386 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1387 /* clear flags and want for any uninstallable package */
1388 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1389 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1390 pkg->state_want = SW_UNKNOWN;
1391 pkg->state_flag = 0;
1394 pkg_vec_free(available_pkgs);
1396 /* update the file owner data structure */
1397 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1398 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1399 for (i = 0; i < installed_pkgs->len; i++) {
1400 pkg_t *pkg = installed_pkgs->pkgs[i];
1401 str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1402 str_list_elt_t *iter, *niter;
1403 if (installed_files == NULL) {
1404 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1407 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1409 iter = niter, niter = str_list_next(installed_files, iter)) {
1410 char *installed_file = (char *) iter->data;
1411 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1412 file_hash_set_file_owner(conf, installed_file, pkg);
1414 pkg_free_installed_files(pkg);
1416 pkg_vec_free(installed_pkgs);
1421 struct pkg_write_filelist_data {
1427 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1429 struct pkg_write_filelist_data *data = data_;
1430 pkg_t *entry = entry_;
1431 if (entry == data->pkg) {
1432 fprintf(data->stream, "%s\n", key);
1436 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1438 struct pkg_write_filelist_data data;
1439 char *list_file_name = NULL;
1443 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1446 opkg_message(conf, OPKG_INFO,
1447 " creating %s.list file\n", pkg->name);
1448 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1449 if (!list_file_name) {
1450 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1453 opkg_message(conf, OPKG_INFO,
1454 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1455 data.stream = fopen(list_file_name, "w");
1457 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1458 list_file_name, strerror(errno));
1463 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1464 fclose(data.stream);
1465 free(list_file_name);
1467 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1472 int pkg_write_changed_filelists(opkg_conf_t *conf)
1474 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1475 hash_table_t *pkg_hash = &conf->pkg_hash;
1481 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1482 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1483 for (i = 0; i < installed_pkgs->len; i++) {
1484 pkg_t *pkg = installed_pkgs->pkgs[i];
1485 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1486 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1487 err = pkg_write_filelist(conf, pkg);
1489 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1492 pkg_vec_free (installed_pkgs);