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)
168 /* revision shares storage with version, so
170 pkg->revision = NULL;
171 /* owned by opkg_conf_t */
173 /* owned by opkg_conf_t */
175 free(pkg->architecture);
176 pkg->architecture = NULL;
177 free(pkg->maintainer);
178 pkg->maintainer = NULL;
181 free(pkg->description);
182 pkg->description = NULL;
183 pkg->state_want = SW_UNKNOWN;
184 pkg->state_flag = SF_OK;
185 pkg->state_status = SS_NOT_INSTALLED;
187 active_list_clear(&pkg->list);
189 free (pkg->replaces);
190 pkg->replaces = NULL;
192 for (i = 0; i < pkg->depends_count; i++)
193 free (pkg->depends_str[i]);
194 free(pkg->depends_str);
195 pkg->depends_str = NULL;
197 for (i = 0; i < pkg->provides_count; i++)
198 free (pkg->provides_str[i]);
199 free(pkg->provides_str);
200 pkg->provides_str = NULL;
202 for (i = 0; i < pkg->conflicts_count; i++)
203 free (pkg->conflicts_str[i]);
204 free(pkg->conflicts_str);
205 pkg->conflicts_str = NULL;
207 for (i = 0; i < pkg->replaces_count; i++)
208 free (pkg->replaces_str[i]);
209 free(pkg->replaces_str);
210 pkg->replaces_str = NULL;
212 for (i = 0; i < pkg->recommends_count; i++)
213 free (pkg->recommends_str[i]);
214 free(pkg->recommends_str);
215 pkg->recommends_str = NULL;
217 for (i = 0; i < pkg->suggests_count; i++)
218 free (pkg->suggests_str[i]);
219 free(pkg->suggests_str);
220 pkg->suggests_str = NULL;
224 int count = pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count;
227 for (x = 0; x < count; x++)
228 compound_depend_deinit (&pkg->depends[x]);
235 for (x = 0; x < pkg->conflicts_count; x++)
236 compound_depend_deinit (&pkg->conflicts[x]);
237 free (pkg->conflicts);
240 free (pkg->provides);
242 pkg->pre_depends_count = 0;
243 free(pkg->pre_depends_str);
244 pkg->pre_depends_str = NULL;
245 pkg->provides_count = 0;
247 pkg->filename = NULL;
248 free(pkg->local_filename);
249 pkg->local_filename = NULL;
250 /* CLEANUP: It'd be nice to pullin the cleanup function from
251 opkg_install.c here. See comment in
252 opkg_install.c:cleanup_temporary_files */
253 free(pkg->tmp_unpack_dir);
254 pkg->tmp_unpack_dir = NULL;
257 #if defined HAVE_SHA256
258 free(pkg->sha256sum);
259 pkg->sha256sum = NULL;
263 free(pkg->installed_size);
264 pkg->installed_size = NULL;
266 pkg->priority = NULL;
269 conffile_list_deinit(&pkg->conffiles);
270 /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
271 since if they are calling deinit, they should know. Maybe do an
272 assertion here instead? */
273 pkg->installed_files_ref_cnt = 1;
274 pkg_free_installed_files(pkg);
280 int pkg_init_from_file(pkg_t *pkg, const char *filename)
283 char **raw, **raw_start;
287 if (err) { return err; }
289 pkg->local_filename = xstrdup(filename);
291 control_file = tmpfile();
292 err = pkg_extract_control_file_to_stream(pkg, control_file);
293 if (err) { return err; }
295 rewind(control_file);
296 raw = raw_start = read_raw_pkgs_from_stream(control_file);
297 pkg_parse_raw(pkg, &raw, NULL, NULL);
299 fclose(control_file);
310 /* Merge any new information in newpkg into oldpkg */
311 /* XXX: CLEANUP: This function shouldn't actually modify anything in
312 newpkg, but should leave it usable. This rework is so that
313 pkg_hash_insert doesn't clobber the pkg that you pass into it. */
315 * uh, i thought that i had originally written this so that it took
316 * two pkgs and returned a new one? we can do that again... -sma
318 int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status)
320 if (oldpkg == newpkg) {
325 oldpkg->src = newpkg->src;
327 oldpkg->dest = newpkg->dest;
328 if (!oldpkg->architecture)
329 oldpkg->architecture = xstrdup(newpkg->architecture);
330 if (!oldpkg->arch_priority)
331 oldpkg->arch_priority = newpkg->arch_priority;
332 if (!oldpkg->section)
333 oldpkg->section = xstrdup(newpkg->section);
334 if(!oldpkg->maintainer)
335 oldpkg->maintainer = xstrdup(newpkg->maintainer);
336 if(!oldpkg->description)
337 oldpkg->description = xstrdup(newpkg->description);
339 /* merge the state_flags from the new package */
340 oldpkg->state_want = newpkg->state_want;
341 oldpkg->state_status = newpkg->state_status;
342 oldpkg->state_flag = newpkg->state_flag;
344 if (oldpkg->state_want == SW_UNKNOWN)
345 oldpkg->state_want = newpkg->state_want;
346 if (oldpkg->state_status == SS_NOT_INSTALLED)
347 oldpkg->state_status = newpkg->state_status;
348 oldpkg->state_flag |= newpkg->state_flag;
351 if (!oldpkg->depends_str && !oldpkg->pre_depends_str && !oldpkg->recommends_str && !oldpkg->suggests_str) {
352 oldpkg->depends_str = newpkg->depends_str;
353 newpkg->depends_str = NULL;
354 oldpkg->depends_count = newpkg->depends_count;
355 newpkg->depends_count = 0;
357 oldpkg->depends = newpkg->depends;
358 newpkg->depends = NULL;
360 oldpkg->pre_depends_str = newpkg->pre_depends_str;
361 newpkg->pre_depends_str = NULL;
362 oldpkg->pre_depends_count = newpkg->pre_depends_count;
363 newpkg->pre_depends_count = 0;
365 oldpkg->recommends_str = newpkg->recommends_str;
366 newpkg->recommends_str = NULL;
367 oldpkg->recommends_count = newpkg->recommends_count;
368 newpkg->recommends_count = 0;
370 oldpkg->suggests_str = newpkg->suggests_str;
371 newpkg->suggests_str = NULL;
372 oldpkg->suggests_count = newpkg->suggests_count;
373 newpkg->suggests_count = 0;
376 if (!oldpkg->provides_str) {
377 oldpkg->provides_str = newpkg->provides_str;
378 newpkg->provides_str = NULL;
379 oldpkg->provides_count = newpkg->provides_count;
380 newpkg->provides_count = 0;
382 oldpkg->provides = newpkg->provides;
383 newpkg->provides = NULL;
386 if (!oldpkg->conflicts_str) {
387 oldpkg->conflicts_str = newpkg->conflicts_str;
388 newpkg->conflicts_str = NULL;
389 oldpkg->conflicts_count = newpkg->conflicts_count;
390 newpkg->conflicts_count = 0;
392 oldpkg->conflicts = newpkg->conflicts;
393 newpkg->conflicts = NULL;
396 if (!oldpkg->replaces_str) {
397 oldpkg->replaces_str = newpkg->replaces_str;
398 newpkg->replaces_str = NULL;
399 oldpkg->replaces_count = newpkg->replaces_count;
400 newpkg->replaces_count = 0;
402 oldpkg->replaces = newpkg->replaces;
403 newpkg->replaces = NULL;
406 if (!oldpkg->filename)
407 oldpkg->filename = xstrdup(newpkg->filename);
408 if (!oldpkg->local_filename)
409 oldpkg->local_filename = xstrdup(newpkg->local_filename);
410 if (!oldpkg->tmp_unpack_dir)
411 oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
413 oldpkg->md5sum = xstrdup(newpkg->md5sum);
414 #if defined HAVE_SHA256
415 if (!oldpkg->sha256sum)
416 oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
419 oldpkg->size = xstrdup(newpkg->size);
420 if (!oldpkg->installed_size)
421 oldpkg->installed_size = xstrdup(newpkg->installed_size);
422 if (!oldpkg->priority)
423 oldpkg->priority = xstrdup(newpkg->priority);
425 oldpkg->source = xstrdup(newpkg->source);
426 if (nv_pair_list_empty(&oldpkg->conffiles)){
427 list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head);
428 conffile_list_init(&newpkg->conffiles);
430 if (!oldpkg->installed_files){
431 oldpkg->installed_files = newpkg->installed_files;
432 oldpkg->installed_files_ref_cnt = newpkg->installed_files_ref_cnt;
433 newpkg->installed_files = NULL;
435 if (!oldpkg->essential)
436 oldpkg->essential = newpkg->essential;
441 abstract_pkg_t *abstract_pkg_new(void)
443 abstract_pkg_t * ab_pkg;
445 ab_pkg = xcalloc(1, sizeof(abstract_pkg_t));
447 if (ab_pkg == NULL) {
448 fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
452 if ( abstract_pkg_init(ab_pkg) < 0 )
458 int abstract_pkg_init(abstract_pkg_t *ab_pkg)
460 ab_pkg->provided_by = abstract_pkg_vec_alloc();
461 if (ab_pkg->provided_by==NULL){
464 ab_pkg->dependencies_checked = 0;
465 ab_pkg->state_status = SS_NOT_INSTALLED;
470 void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){
473 char **raw_start=NULL;
475 size_t str_size = strlen(pkg->dest->info_dir)+strlen(pkg->name)+12;
476 temp_str = (char *) alloca (str_size);
477 memset(temp_str, 0 , str_size);
479 if (temp_str == NULL ){
480 opkg_message(conf, OPKG_INFO, "Out of memory in %s\n", __FUNCTION__);
483 sprintf( temp_str,"%s/%s.control",pkg->dest->info_dir,pkg->name);
485 raw = raw_start = read_raw_pkgs_from_file(temp_str);
487 opkg_message(conf, OPKG_ERROR, "Unable to open the control file in %s\n", __FUNCTION__);
492 if (!pkg_valorize_other_field(pkg, &raw ) == 0) {
493 opkg_message(conf, OPKG_DEBUG, "unable to read control file for %s. May be empty\n", pkg->name);
508 void pkg_formatted_field(FILE *fp, pkg_t *pkg, const char *field)
511 int flag_provide_false = 0;
513 if (strlen(field) < PKG_MINIMUM_FIELD_NAME_LEN) {
514 goto UNKNOWN_FMT_FIELD;
521 if (strcasecmp(field, "Architecture") == 0) {
522 if (pkg->architecture) {
523 fprintf(fp, "Architecture: %s\n", pkg->architecture);
525 } else if (strcasecmp(field, "Auto-Installed") == 0) {
526 if (pkg->auto_installed)
527 fprintf(fp, "Auto-Installed: yes\n");
529 goto UNKNOWN_FMT_FIELD;
534 if (strcasecmp(field, "Conffiles") == 0) {
535 conffile_list_elt_t *iter;
537 if (nv_pair_list_empty(&pkg->conffiles))
540 fprintf(fp, "Conffiles:\n");
541 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
542 if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) {
543 fprintf(fp, "%s %s\n",
544 ((conffile_t *)iter->data)->name,
545 ((conffile_t *)iter->data)->value);
548 } else if (strcasecmp(field, "Conflicts") == 0) {
549 if (pkg->conflicts_count) {
550 fprintf(fp, "Conflicts:");
551 for(i = 0; i < pkg->conflicts_count; i++) {
552 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->conflicts_str[i]);
557 goto UNKNOWN_FMT_FIELD;
562 if (strcasecmp(field, "Depends") == 0) {
563 if (pkg->depends_count) {
564 fprintf(fp, "Depends:");
565 for(i = 0; i < pkg->depends_count; i++) {
566 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->depends_str[i]);
570 } else if (strcasecmp(field, "Description") == 0) {
571 if (pkg->description) {
572 fprintf(fp, "Description: %s\n", pkg->description);
575 goto UNKNOWN_FMT_FIELD;
580 if (pkg->essential) {
581 fprintf(fp, "Essential: yes\n");
587 fprintf(fp, "Filename: %s\n", pkg->filename);
592 if (strcasecmp(field, "Installed-Size") == 0) {
593 fprintf(fp, "Installed-Size: %s\n", pkg->installed_size);
594 } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) {
595 fprintf(fp, "Installed-Time: %lu\n", pkg->installed_time);
600 if (strcasecmp(field, "Maintainer") == 0) {
601 if (pkg->maintainer) {
602 fprintf(fp, "maintainer: %s\n", pkg->maintainer);
604 } else if (strcasecmp(field, "MD5sum") == 0) {
606 fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
609 goto UNKNOWN_FMT_FIELD;
614 if (strcasecmp(field, "Package") == 0) {
615 fprintf(fp, "Package: %s\n", pkg->name);
616 } else if (strcasecmp(field, "Priority") == 0) {
617 fprintf(fp, "Priority: %s\n", pkg->priority);
618 } else if (strcasecmp(field, "Provides") == 0) {
619 if (pkg->provides_count) {
620 /* Here we check if the opkg_internal_use_only is used, and we discard it.*/
621 for ( i=0; i < pkg->provides_count; i++ ){
622 if (strstr(pkg->provides_str[i],"opkg_internal_use_only")!=NULL) {
623 memset (pkg->provides_str[i],'\x0',strlen(pkg->provides_str[i])); /* Pigi clear my trick flag, just in case */
624 flag_provide_false = 1;
627 if ( !flag_provide_false || /* Pigi there is not my trick flag */
628 ((flag_provide_false) && (pkg->provides_count > 1))){ /* Pigi There is, but we also have others Provides */
629 fprintf(fp, "Provides:");
630 for(i = 0; i < pkg->provides_count; i++) {
631 if (strlen(pkg->provides_str[i])>0) {
632 fprintf(fp, "%s %s", i == 1 ? "" : ",", pkg->provides_str[i]);
639 goto UNKNOWN_FMT_FIELD;
644 if (strcasecmp (field, "Replaces") == 0) {
645 if (pkg->replaces_count) {
646 fprintf(fp, "Replaces:");
647 for (i = 0; i < pkg->replaces_count; i++) {
648 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->replaces_str[i]);
652 } else if (strcasecmp (field, "Recommends") == 0) {
653 if (pkg->recommends_count) {
654 fprintf(fp, "Recommends:");
655 for(i = 0; i < pkg->recommends_count; i++) {
656 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->recommends_str[i]);
661 goto UNKNOWN_FMT_FIELD;
666 if (strcasecmp(field, "Section") == 0) {
668 fprintf(fp, "Section: %s\n", pkg->section);
670 #if defined HAVE_SHA256
671 } else if (strcasecmp(field, "SHA256sum") == 0) {
672 if (pkg->sha256sum) {
673 fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
676 } else if (strcasecmp(field, "Size") == 0) {
678 fprintf(fp, "Size: %s\n", pkg->size);
680 } else if (strcasecmp(field, "Source") == 0) {
682 fprintf(fp, "Source: %s\n", pkg->source);
684 } else if (strcasecmp(field, "Status") == 0) {
685 char *pflag = pkg_state_flag_to_str(pkg->state_flag);
686 char *pstat = pkg_state_status_to_str(pkg->state_status);
687 char *pwant = pkg_state_want_to_str(pkg->state_want);
689 if (pflag == NULL || pstat == NULL || pwant == NULL)
692 fprintf(fp, "Status: %s %s %s\n", pwant, pflag, pstat);
697 } else if (strcasecmp(field, "Suggests") == 0) {
698 if (pkg->suggests_count) {
699 fprintf(fp, "Suggests:");
700 for(i = 0; i < pkg->suggests_count; i++) {
701 fprintf(fp, "%s %s", i == 0 ? "" : ",", pkg->suggests_str[i]);
706 goto UNKNOWN_FMT_FIELD;
711 if (strcasecmp(field, "Tags") == 0) {
713 fprintf(fp, "Tags: %s\n", pkg->tags);
720 char *version = pkg_version_str_alloc(pkg);
723 fprintf(fp, "Version: %s\n", version);
728 goto UNKNOWN_FMT_FIELD;
734 fprintf(stderr, "%s: ERROR: Unknown field name: %s\n", __FUNCTION__, field);
737 void pkg_formatted_info(FILE *fp, pkg_t *pkg)
739 pkg_formatted_field(fp, pkg, "Package");
740 pkg_formatted_field(fp, pkg, "Version");
741 pkg_formatted_field(fp, pkg, "Depends");
742 pkg_formatted_field(fp, pkg, "Recommends");
743 pkg_formatted_field(fp, pkg, "Suggests");
744 pkg_formatted_field(fp, pkg, "Provides");
745 pkg_formatted_field(fp, pkg, "Replaces");
746 pkg_formatted_field(fp, pkg, "Conflicts");
747 pkg_formatted_field(fp, pkg, "Status");
748 pkg_formatted_field(fp, pkg, "Section");
749 pkg_formatted_field(fp, pkg, "Essential");
750 pkg_formatted_field(fp, pkg, "Architecture");
751 pkg_formatted_field(fp, pkg, "Maintainer");
752 pkg_formatted_field(fp, pkg, "MD5sum");
753 pkg_formatted_field(fp, pkg, "Size");
754 pkg_formatted_field(fp, pkg, "Filename");
755 pkg_formatted_field(fp, pkg, "Conffiles");
756 pkg_formatted_field(fp, pkg, "Source");
757 pkg_formatted_field(fp, pkg, "Description");
758 pkg_formatted_field(fp, pkg, "Installed-Time");
759 pkg_formatted_field(fp, pkg, "Tags");
763 void pkg_print_status(pkg_t * pkg, FILE * file)
769 /* XXX: QUESTION: Do we actually want more fields here? The
770 original idea was to save space by installing only what was
771 needed for actual computation, (package, version, status,
772 essential, conffiles). The assumption is that all other fields
773 can be found in th available file.
775 But, someone proposed the idea to make it possible to
776 reconstruct a .opk from an installed package, (ie. for beaming
777 from one handheld to another). So, maybe we actually want a few
778 more fields here, (depends, suggests, etc.), so that that would
779 be guaranteed to work even in the absence of more information
780 from the available file.
782 28-MAR-03: kergoth and I discussed this yesterday. We think
783 the essential info needs to be here for all installed packages
784 because they may not appear in the Packages files on various
785 feeds. Furthermore, one should be able to install from URL or
786 local storage without requiring a Packages file from any feed.
789 pkg_formatted_field(file, pkg, "Package");
790 pkg_formatted_field(file, pkg, "Version");
791 pkg_formatted_field(file, pkg, "Depends");
792 pkg_formatted_field(file, pkg, "Recommends");
793 pkg_formatted_field(file, pkg, "Suggests");
794 pkg_formatted_field(file, pkg, "Provides");
795 pkg_formatted_field(file, pkg, "Replaces");
796 pkg_formatted_field(file, pkg, "Conflicts");
797 pkg_formatted_field(file, pkg, "Status");
798 pkg_formatted_field(file, pkg, "Essential");
799 pkg_formatted_field(file, pkg, "Architecture");
800 pkg_formatted_field(file, pkg, "Conffiles");
801 pkg_formatted_field(file, pkg, "Installed-Time");
802 pkg_formatted_field(file, pkg, "Auto-Installed");
807 * libdpkg - Debian packaging suite library routines
808 * vercmp.c - comparison of version numbers
810 * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
812 int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg)
816 if (pkg->epoch > ref_pkg->epoch) {
820 if (pkg->epoch < ref_pkg->epoch) {
824 r = verrevcmp(pkg->version, ref_pkg->version);
829 r = verrevcmp(pkg->revision, ref_pkg->revision);
837 /* assume ascii; warning: evaluates x multiple times! */
838 #define order(x) ((x) == '~' ? -1 \
841 : isalpha((x)) ? (x) \
844 static int verrevcmp(const char *val, const char *ref) {
848 while (*val || *ref) {
851 while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
852 int vc= order(*val), rc= order(*ref);
853 if (vc != rc) return vc - rc;
857 while ( *val == '0' ) val++;
858 while ( *ref == '0' ) ref++;
859 while (isdigit(*val) && isdigit(*ref)) {
860 if (!first_diff) first_diff= *val - *ref;
863 if (isdigit(*val)) return 1;
864 if (isdigit(*ref)) return -1;
865 if (first_diff) return first_diff;
870 int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op)
874 r = pkg_compare_versions(it, ref);
876 if (strcmp(op, "<=") == 0 || strcmp(op, "<") == 0) {
880 if (strcmp(op, ">=") == 0 || strcmp(op, ">") == 0) {
884 if (strcmp(op, "<<") == 0) {
888 if (strcmp(op, ">>") == 0) {
892 if (strcmp(op, "=") == 0) {
896 fprintf(stderr, "unknown operator: %s", op);
900 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
902 const pkg_t *a = *(const pkg_t**) p1;
903 const pkg_t *b = *(const pkg_t**) p2;
906 if (!a->name || !b->name) {
907 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->name=%p b=%p b->name=%p\n",
908 a, a->name, b, b->name);
912 namecmp = strcmp(a->name, b->name);
915 vercmp = pkg_compare_versions(a, b);
918 if (!a->arch_priority || !b->arch_priority) {
919 fprintf(stderr, "pkg_name_version_and_architecture_compare: a=%p a->arch_priority=%i b=%p b->arch_priority=%i\n",
920 a, a->arch_priority, b, b->arch_priority);
923 if (a->arch_priority > b->arch_priority)
925 if (a->arch_priority < b->arch_priority)
930 int abstract_pkg_name_compare(const void *p1, const void *p2)
932 const abstract_pkg_t *a = *(const abstract_pkg_t **)p1;
933 const abstract_pkg_t *b = *(const abstract_pkg_t **)p2;
934 if (!a->name || !b->name) {
935 fprintf(stderr, "abstract_pkg_name_compare: a=%p a->name=%p b=%p b->name=%p\n",
936 a, a->name, b, b->name);
939 return strcmp(a->name, b->name);
943 char *pkg_version_str_alloc(pkg_t *pkg)
945 char *complete_version;
950 sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
952 epoch_str = xstrdup("");
955 if (pkg->revision && strlen(pkg->revision)) {
956 sprintf_alloc(&revision_str, "-%s", pkg->revision);
958 revision_str = xstrdup("");
962 sprintf_alloc(&complete_version, "%s%s%s",
963 epoch_str, pkg->version, revision_str);
968 return complete_version;
971 str_list_t *pkg_get_installed_files(pkg_t *pkg)
974 char *list_file_name = NULL;
975 FILE *list_file = NULL;
977 char *installed_file_name;
980 pkg->installed_files_ref_cnt++;
982 if (pkg->installed_files) {
983 return pkg->installed_files;
986 pkg->installed_files = str_list_alloc();
988 /* For uninstalled packages, get the file list directly from the package.
989 For installed packages, look at the package.list file in the database.
991 if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) {
992 if (pkg->local_filename == NULL) {
993 return pkg->installed_files;
995 /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
996 file. In other words, change deb_extract so that it can
997 simply return the file list as a char *[] rather than
998 insisting on writing in to a FILE * as it does now. */
999 list_file = tmpfile();
1000 err = pkg_extract_data_file_names_to_stream(pkg, list_file);
1003 fprintf(stderr, "%s: Error extracting file list from %s: %s\n",
1004 __FUNCTION__, pkg->local_filename, strerror(err));
1005 return pkg->installed_files;
1009 sprintf_alloc(&list_file_name, "%s/%s.list",
1010 pkg->dest->info_dir, pkg->name);
1011 if (! file_exists(list_file_name)) {
1012 free(list_file_name);
1013 return pkg->installed_files;
1016 list_file = fopen(list_file_name, "r");
1017 if (list_file == NULL) {
1018 fprintf(stderr, "WARNING: Cannot open %s: %s\n",
1019 list_file_name, strerror(errno));
1020 free(list_file_name);
1021 return pkg->installed_files;
1023 free(list_file_name);
1026 rootdirlen = strlen( pkg->dest->root_dir );
1030 line = file_read_line_alloc(list_file);
1037 /* Take pains to avoid uglies like "/./" in the middle of file_name. */
1038 if( strncmp( pkg->dest->root_dir,
1041 if (*file_name == '.') {
1044 if (*file_name == '/') {
1048 /* Freed in pkg_free_installed_files */
1049 sprintf_alloc(&installed_file_name, "%s%s", pkg->dest->root_dir, file_name);
1051 // already contains root_dir as header -> ABSOLUTE
1052 sprintf_alloc(&installed_file_name, "%s", file_name);
1054 str_list_append(pkg->installed_files, installed_file_name);
1055 free(installed_file_name);
1061 return pkg->installed_files;
1064 /* XXX: CLEANUP: This function and it's counterpart,
1065 (pkg_get_installed_files), do not match our init/deinit naming
1066 convention. Nor the alloc/free convention. But, then again, neither
1067 of these conventions currrently fit the way these two functions
1069 int pkg_free_installed_files(pkg_t *pkg)
1071 pkg->installed_files_ref_cnt--;
1073 if (pkg->installed_files_ref_cnt > 0)
1076 if (pkg->installed_files) {
1077 str_list_purge(pkg->installed_files);
1080 pkg->installed_files = NULL;
1085 int pkg_remove_installed_files_list(opkg_conf_t *conf, pkg_t *pkg)
1088 char *list_file_name;
1090 //I don't think pkg_free_installed_files should be called here. Jamey
1091 //pkg_free_installed_files(pkg);
1093 sprintf_alloc(&list_file_name, "%s/%s.list",
1094 pkg->dest->info_dir, pkg->name);
1095 if (!conf->noaction) {
1096 err = unlink(list_file_name);
1097 free(list_file_name);
1106 conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name)
1108 conffile_list_elt_t *iter;
1109 conffile_t *conffile;
1115 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
1116 conffile = (conffile_t *)iter->data;
1118 if (strcmp(conffile->name, file_name) == 0) {
1126 int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg,
1127 const char *script, const char *args)
1136 /* XXX: CLEANUP: There must be a better way to handle maintainer
1137 scripts when running with offline_root mode and/or a dest other
1138 than '/'. I've been playing around with some clever chroot
1139 tricks and I might come up with something workable. */
1141 * Attempt to provide a restricted environment for offline operation
1142 * Need the following set as a minimum:
1143 * OPKG_OFFLINE_ROOT = absolute path to root dir
1144 * D = absolute path to root dir (for OE generated postinst)
1145 * PATH = something safe (a restricted set of utilities)
1148 if (conf->offline_root) {
1149 if (conf->offline_root_path) {
1150 setenv("PATH", conf->offline_root_path, 1);
1152 opkg_message(conf, OPKG_NOTICE,
1153 "(offline root mode: not running %s.%s)\n", pkg->name, script);
1156 setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1);
1157 setenv("D", conf->offline_root, 1);
1160 /* XXX: FEATURE: When conf->offline_root is set, we should run the
1161 maintainer script within a chroot environment. */
1163 /* Installed packages have scripts in pkg->dest->info_dir, uninstalled packages
1164 have scripts in pkg->tmp_unpack_dir. */
1165 if (pkg->state_status == SS_INSTALLED || pkg->state_status == SS_UNPACKED) {
1166 if (pkg->dest == NULL) {
1167 fprintf(stderr, "%s: ERROR: installed package %s has a NULL dest\n",
1168 __FUNCTION__, pkg->name);
1171 sprintf_alloc(&path, "%s/%s.%s", pkg->dest->info_dir, pkg->name, script);
1173 if (pkg->tmp_unpack_dir == NULL) {
1174 fprintf(stderr, "%s: ERROR: uninstalled package %s has a NULL tmp_unpack_dir\n",
1175 __FUNCTION__, pkg->name);
1178 sprintf_alloc(&path, "%s/%s", pkg->tmp_unpack_dir, script);
1181 opkg_message(conf, OPKG_INFO, "Running script %s\n", path);
1184 pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir, 1);
1186 if (! file_exists(path)) {
1191 sprintf_alloc(&cmd, "%s %s", path, args);
1198 fprintf(stderr, "%s script returned status %d\n", script, err);
1205 char *pkg_state_want_to_str(pkg_state_want_t sw)
1209 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1210 if (pkg_state_want_map[i].value == sw) {
1211 return xstrdup(pkg_state_want_map[i].str);
1215 fprintf(stderr, "%s: ERROR: Illegal value for state_want: %d\n",
1217 return xstrdup("<STATE_WANT_UNKNOWN>");
1220 pkg_state_want_t pkg_state_want_from_str(char *str)
1224 for (i=0; i < ARRAY_SIZE(pkg_state_want_map); i++) {
1225 if (strcmp(str, pkg_state_want_map[i].str) == 0) {
1226 return pkg_state_want_map[i].value;
1230 fprintf(stderr, "%s: ERROR: Illegal value for state_want string: %s\n",
1235 char *pkg_state_flag_to_str(pkg_state_flag_t sf)
1238 int len = 3; /* ok\000 is minimum */
1241 /* clear the temporary flags before converting to string */
1242 sf &= SF_NONVOLATILE_FLAGS;
1245 return xstrdup("ok");
1248 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1249 if (sf & pkg_state_flag_map[i].value) {
1250 len += strlen(pkg_state_flag_map[i].str) + 1;
1255 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1256 if (sf & pkg_state_flag_map[i].value) {
1257 strcat(str, pkg_state_flag_map[i].str);
1262 str[len-1] = 0; /* squash last comma */
1267 pkg_state_flag_t pkg_state_flag_from_str(const char *str)
1272 if (strcmp(str, "ok") == 0) {
1275 for (i=0; i < ARRAY_SIZE(pkg_state_flag_map); i++) {
1276 const char *sfname = pkg_state_flag_map[i].str;
1277 int sfname_len = strlen(sfname);
1278 if (strncmp(str, sfname, sfname_len) == 0) {
1279 sf |= pkg_state_flag_map[i].value;
1281 if (str[0] == ',') {
1292 char *pkg_state_status_to_str(pkg_state_status_t ss)
1296 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1297 if (pkg_state_status_map[i].value == ss) {
1298 return xstrdup(pkg_state_status_map[i].str);
1302 fprintf(stderr, "%s: ERROR: Illegal value for state_status: %d\n",
1304 return xstrdup("<STATE_STATUS_UNKNOWN>");
1307 pkg_state_status_t pkg_state_status_from_str(const char *str)
1311 for (i=0; i < ARRAY_SIZE(pkg_state_status_map); i++) {
1312 if (strcmp(str, pkg_state_status_map[i].str) == 0) {
1313 return pkg_state_status_map[i].value;
1317 fprintf(stderr, "%s: ERROR: Illegal value for state_status string: %s\n",
1319 return SS_NOT_INSTALLED;
1322 int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg)
1324 nv_pair_list_elt_t *l;
1326 if (!pkg->architecture)
1329 list_for_each_entry(l , &conf->arch_list.head, node) {
1330 nv_pair_t *nv = (nv_pair_t *)l->data;
1331 if (strcmp(nv->name, pkg->architecture) == 0) {
1332 opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name);
1337 opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name);
1341 int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname)
1343 nv_pair_list_elt_t *l;
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, archname) == 0) {
1348 int priority = strtol(nv->value, NULL, 0);
1355 int pkg_info_preinstall_check(opkg_conf_t *conf)
1358 hash_table_t *pkg_hash = &conf->pkg_hash;
1359 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1360 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1362 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: updating arch priority for each package\n");
1363 pkg_hash_fetch_available(pkg_hash, available_pkgs);
1364 /* update arch_priority for each package */
1365 for (i = 0; i < available_pkgs->len; i++) {
1366 pkg_t *pkg = available_pkgs->pkgs[i];
1367 int arch_priority = 1;
1370 // opkg_message(conf, OPKG_DEBUG2, " package %s version=%s arch=%p:", pkg->name, pkg->version, pkg->architecture);
1371 if (pkg->architecture)
1372 arch_priority = pkg_get_arch_priority(conf, pkg->architecture);
1374 opkg_message(conf, OPKG_ERROR, "pkg_info_preinstall_check: no architecture for package %s\n", pkg->name);
1375 // opkg_message(conf, OPKG_DEBUG2, "%s arch_priority=%d\n", pkg->architecture, arch_priority);
1376 pkg->arch_priority = arch_priority;
1379 for (i = 0; i < available_pkgs->len; i++) {
1380 pkg_t *pkg = available_pkgs->pkgs[i];
1381 if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) {
1382 /* clear flags and want for any uninstallable package */
1383 opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n",
1384 pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want);
1385 pkg->state_want = SW_UNKNOWN;
1386 pkg->state_flag = 0;
1389 pkg_vec_free(available_pkgs);
1391 /* update the file owner data structure */
1392 opkg_message(conf, OPKG_INFO, "pkg_info_preinstall_check: update file owner list\n");
1393 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1394 for (i = 0; i < installed_pkgs->len; i++) {
1395 pkg_t *pkg = installed_pkgs->pkgs[i];
1396 str_list_t *installed_files = pkg_get_installed_files(pkg); /* this causes installed_files to be cached */
1397 str_list_elt_t *iter, *niter;
1398 if (installed_files == NULL) {
1399 opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name);
1402 for (iter = str_list_first(installed_files), niter = str_list_next(installed_files, iter);
1404 iter = niter, niter = str_list_next(installed_files, iter)) {
1405 char *installed_file = (char *) iter->data;
1406 // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file);
1407 file_hash_set_file_owner(conf, installed_file, pkg);
1409 pkg_free_installed_files(pkg);
1411 pkg_vec_free(installed_pkgs);
1416 struct pkg_write_filelist_data {
1422 void pkg_write_filelist_helper(const char *key, void *entry_, void *data_)
1424 struct pkg_write_filelist_data *data = data_;
1425 pkg_t *entry = entry_;
1426 if (entry == data->pkg) {
1427 fprintf(data->stream, "%s\n", key);
1431 int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg)
1433 struct pkg_write_filelist_data data;
1434 char *list_file_name = NULL;
1438 opkg_message(conf, OPKG_ERROR, "Null pkg\n");
1441 opkg_message(conf, OPKG_INFO,
1442 " creating %s.list file\n", pkg->name);
1443 sprintf_alloc(&list_file_name, "%s/%s.list", pkg->dest->info_dir, pkg->name);
1444 if (!list_file_name) {
1445 opkg_message(conf, OPKG_ERROR, "Failed to alloc list_file_name\n");
1448 opkg_message(conf, OPKG_INFO,
1449 " creating %s file for pkg %s\n", list_file_name, pkg->name);
1450 data.stream = fopen(list_file_name, "w");
1452 opkg_message(conf, OPKG_ERROR, "Could not open %s for writing: %s\n",
1453 list_file_name, strerror(errno));
1458 hash_table_foreach(&conf->file_hash, pkg_write_filelist_helper, &data);
1459 fclose(data.stream);
1460 free(list_file_name);
1462 pkg->state_flag &= ~SF_FILELIST_CHANGED;
1467 int pkg_write_changed_filelists(opkg_conf_t *conf)
1469 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
1470 hash_table_t *pkg_hash = &conf->pkg_hash;
1476 opkg_message(conf, OPKG_INFO, "%s: saving changed filelists\n", __FUNCTION__);
1477 pkg_hash_fetch_all_installed(pkg_hash, installed_pkgs);
1478 for (i = 0; i < installed_pkgs->len; i++) {
1479 pkg_t *pkg = installed_pkgs->pkgs[i];
1480 if (pkg->state_flag & SF_FILELIST_CHANGED) {
1481 opkg_message(conf, OPKG_DEBUG, "Calling pkg_write_filelist for pkg=%s from %s\n", pkg->name, __FUNCTION__);
1482 err = pkg_write_filelist(conf, pkg);
1484 opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
1487 pkg_vec_free (installed_pkgs);