1 /* opkg_cmd.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.
24 #include "opkg_conf.h"
26 #include "opkg_message.h"
29 #include "pkg_parse.h"
30 #include "sprintf_alloc.h"
32 #include "file_util.h"
34 #include "libbb/libbb.h"
35 #include "opkg_utils.h"
36 #include "opkg_defines.h"
37 #include "opkg_download.h"
38 #include "opkg_install.h"
39 #include "opkg_upgrade.h"
40 #include "opkg_remove.h"
41 #include "opkg_configure.h"
42 #include "opkg_message.h"
46 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv);
47 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv);
48 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv);
49 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv);
50 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv);
51 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv);
52 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv);
53 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv);
54 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
55 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv);
56 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
57 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
58 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
70 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
71 static int pkg_mark_provides(pkg_t *pkg);
73 /* XXX: CLEANUP: The usage strings should be incorporated into this
74 array for easier maintenance */
75 static opkg_cmd_t cmds[] = {
76 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
77 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
78 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
79 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
80 {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
81 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
82 {"list-upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
83 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
84 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
85 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
86 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
87 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
88 {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
89 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
90 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
91 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
92 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
93 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
94 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
95 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
96 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
97 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
98 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
99 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
100 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
101 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
102 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
103 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
104 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
105 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
106 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
109 static void print_pkg(pkg_t *pkg)
111 char *version = pkg_version_str_alloc(pkg);
112 if (pkg->description)
113 printf("%s - %s - %s\n", pkg->name, version, pkg->description);
115 printf("%s - %s\n", pkg->name, version);
119 int opkg_state_changed;
120 static void write_status_files_if_changed(opkg_conf_t *conf)
122 if (opkg_state_changed && !conf->noaction) {
123 opkg_message(conf, OPKG_INFO,
124 " writing status file\n");
125 opkg_conf_write_status_files(conf);
126 pkg_write_changed_filelists(conf);
128 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
133 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
135 opkg_cmd_t *opkg_cmd_find(const char *name)
140 for (i=0; i < num_cmds; i++) {
142 if (strcmp(name, cmd->name) == 0) {
150 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
154 result = (cmd->fun)(conf, argc, argv);
162 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
168 pkg_src_list_elt_t *iter;
172 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
174 if (! file_is_dir(lists_dir)) {
175 if (file_exists(lists_dir)) {
176 opkg_message(conf, OPKG_ERROR,
177 "%s: ERROR: %s exists, but is not a directory\n",
178 __FUNCTION__, lists_dir);
182 err = file_mkdir_hier(lists_dir, 0755);
184 opkg_message(conf, OPKG_ERROR,
185 "%s: ERROR: failed to make directory %s: %s\n",
186 __FUNCTION__, lists_dir, strerror(errno));
194 sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
195 if (mkdtemp (tmp) == NULL) {
201 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
202 char *url, *list_file_name;
204 src = (pkg_src_t *)iter->data;
206 if (src->extra_data) /* debian style? */
207 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
208 src->gzip ? "Packages.gz" : "Packages");
210 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
212 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
217 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
218 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
220 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
221 in = fopen (tmp_file_name, "r");
222 out = fopen (list_file_name, "w");
231 unlink (tmp_file_name);
235 err = opkg_download(conf, url, list_file_name, NULL, NULL);
239 opkg_message(conf, OPKG_NOTICE,
240 "Updated list of available packages in %s\n",
244 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
245 if (conf->check_signature) {
246 /* download detached signitures to verify the package lists */
247 /* get the url for the sig file */
248 if (src->extra_data) /* debian style? */
249 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
252 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
254 /* create temporary file for it */
257 /* Put the signature in the right place */
258 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
260 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
263 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
266 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
268 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
270 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
272 /* We shouldn't unlink the signature ! */
273 // unlink (tmp_file_name);
274 free (tmp_file_name);
280 free(list_file_name);
290 struct opkg_intercept
296 typedef struct opkg_intercept *opkg_intercept_t;
298 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
300 opkg_intercept_t ctx;
303 ctx = xcalloc(1, sizeof (*ctx));
304 ctx->oldpath = xstrdup(getenv("PATH"));
305 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
306 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX", conf->tmp_dir);
308 if (mkdtemp(ctx->statedir) == NULL) {
309 fprintf(stderr, "%s: mkdtemp: %s\n", __FUNCTION__, strerror(errno));
317 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
318 setenv("PATH", newpath, 1);
324 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
329 setenv ("PATH", ctx->oldpath, 1);
332 dir = opendir (ctx->statedir);
335 while (de = readdir (dir), de != NULL) {
338 if (de->d_name[0] == '.')
341 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
342 if (access (path, X_OK) == 0) {
343 const char *argv[] = {"sh", "-c", path, NULL};
350 perror (ctx->statedir);
353 free (ctx->statedir);
359 /* For package pkg do the following: If it is already visited, return. If not,
360 add it in visited list and recurse to its deps. Finally, add it to ordered
362 pkg_vec all contains all available packages in repos.
363 pkg_vec visited contains packages already visited by this function, and is
364 used to end recursion and avoid an infinite loop on graph cycles.
365 pkg_vec ordered will finally contain the ordered set of packages.
367 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
368 pkg_vec_t *visited, pkg_vec_t *ordered)
373 compound_depend_t * compound_depend;
374 depend_t ** possible_satisfiers;
375 abstract_pkg_t *abpkg;
376 abstract_pkg_t **dependents;
378 /* If it's just an available package, that is, not installed and not even
380 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
381 would do here. However, if there is an intermediate node (pkg) that is
382 configured and installed between two unpacked packages, the latter
383 won't be properly reordered, unless all installed/unpacked pkgs are
385 if (pkg->state_status == SS_NOT_INSTALLED)
388 /* If the package has already been visited (by this function), skip it */
389 for(j = 0; j < visited->len; j++)
390 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
391 opkg_message(conf, OPKG_INFO,
392 " pkg: %s already visited\n", pkg->name);
396 pkg_vec_insert(visited, pkg);
398 count = pkg->pre_depends_count + pkg->depends_count + \
399 pkg->recommends_count + pkg->suggests_count;
401 opkg_message(conf, OPKG_INFO,
402 " pkg: %s\n", pkg->name);
404 /* Iterate over all the dependencies of pkg. For each one, find a package
405 that is either installed or unpacked and satisfies this dependency.
406 (there should only be one such package per dependency installed or
407 unpacked). Then recurse to the dependency package */
408 for (j=0; j < count ; j++) {
409 compound_depend = &pkg->depends[j];
410 possible_satisfiers = compound_depend->possibilities;
411 for (k=0; k < compound_depend->possibility_count ; k++) {
412 abpkg = possible_satisfiers[k]->pkg;
413 dependents = abpkg->provided_by->pkgs;
415 if (dependents != NULL)
416 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
417 opkg_message(conf, OPKG_INFO,
418 " Descending on pkg: %s\n",
419 dependents [l]->name);
421 /* find whether dependent l is installed or unpacked,
422 * and then find which package in the list satisfies it */
423 for(m = 0; m < all->len; m++) {
425 if ( dep->state_status != SS_NOT_INSTALLED)
426 if ( ! strcmp(dep->name, dependents[l]->name)) {
427 opkg_recurse_pkgs_in_order(conf, dep, all,
429 /* Stop the outer loop */
430 l = abpkg->provided_by->len;
431 /* break from the inner loop */
440 /* When all recursions from this node down, are over, and all
441 dependencies have been added in proper order in the ordered array, add
442 also the package pkg to ordered array */
443 pkg_vec_insert(ordered, pkg);
449 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
451 pkg_vec_t *all, *ordered, *visited;
457 opkg_message(conf, OPKG_INFO,
458 "Configuring unpacked packages\n");
461 all = pkg_vec_alloc();
463 pkg_hash_fetch_available(&conf->pkg_hash, all);
465 /* Reorder pkgs in order to be configured according to the Depends: tag
467 opkg_message(conf, OPKG_INFO,
468 "Reordering packages before configuring them...\n");
469 ordered = pkg_vec_alloc();
470 visited = pkg_vec_alloc();
471 for(i = 0; i < all->len; i++) {
473 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
476 ic = opkg_prep_intercepts (conf);
482 for(i = 0; i < all->len; i++) {
485 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
488 if (pkg->state_status == SS_UNPACKED) {
489 opkg_message(conf, OPKG_NOTICE,
490 "Configuring %s\n", pkg->name);
492 r = opkg_configure(conf, pkg);
494 pkg->state_status = SS_INSTALLED;
495 pkg->parent->state_status = SS_INSTALLED;
496 pkg->state_flag &= ~SF_PREFER;
504 r = opkg_finalize_intercepts (ic);
510 pkg_vec_free(ordered);
511 pkg_vec_free(visited);
516 static opkg_conf_t *global_conf;
518 static void sigint_handler(int sig)
520 signal(sig, SIG_DFL);
521 opkg_message(NULL, OPKG_NOTICE,
522 "opkg: interrupted. writing out status database\n");
523 write_status_files_if_changed(global_conf);
527 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
534 signal(SIGINT, sigint_handler);
537 * Now scan through package names and install
539 for (i=0; i < argc; i++) {
542 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
543 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
544 if (err != EINVAL && err != 0)
547 pkg_info_preinstall_check(conf);
549 for (i=0; i < argc; i++) {
551 err = opkg_install_by_name(conf, arg);
552 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
553 opkg_message(conf, OPKG_ERROR,
554 "Cannot find package %s.\n",
559 opkg_configure_packages(conf, NULL);
561 write_status_files_if_changed(conf);
566 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
573 signal(SIGINT, sigint_handler);
576 for (i=0; i < argc; i++) {
579 err = opkg_prepare_url_for_install(conf, arg, &arg);
580 if (err != EINVAL && err != 0)
583 pkg_info_preinstall_check(conf);
585 for (i=0; i < argc; i++) {
587 if (conf->restrict_to_default_dest) {
588 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
592 opkg_message(conf, OPKG_NOTICE,
593 "Package %s not installed in %s\n",
594 argv[i], conf->default_dest->name);
598 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
602 opkg_upgrade_pkg(conf, pkg);
604 opkg_install_by_name(conf, arg);
608 pkg_vec_t *installed = pkg_vec_alloc();
610 pkg_info_preinstall_check(conf);
612 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
613 for (i = 0; i < installed->len; i++) {
614 pkg = installed->pkgs[i];
615 opkg_upgrade_pkg(conf, pkg);
617 pkg_vec_free(installed);
620 opkg_configure_packages(conf, NULL);
622 write_status_files_if_changed(conf);
627 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
633 pkg_info_preinstall_check(conf);
634 for (i = 0; i < argc; i++) {
637 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
639 opkg_message(conf, OPKG_ERROR,
640 "Cannot find package %s.\n"
641 "Check the spelling or perhaps run 'opkg update'\n",
646 err = opkg_download_pkg(conf, pkg, ".");
649 opkg_message(conf, OPKG_ERROR,
650 "Failed to download %s\n", pkg->name);
652 opkg_message(conf, OPKG_NOTICE,
653 "Downloaded %s as %s\n",
654 pkg->name, pkg->local_filename);
662 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
665 pkg_vec_t *available;
667 char *pkg_name = NULL;
672 available = pkg_vec_alloc();
673 pkg_hash_fetch_available(&conf->pkg_hash, available);
674 pkg_vec_sort(available, pkg_compare_names);
675 for (i=0; i < available->len; i++) {
676 pkg = available->pkgs[i];
677 /* if we have package name or pattern and pkg does not match, then skip it */
678 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
682 pkg_vec_free(available);
688 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
691 pkg_vec_t *available;
693 char *pkg_name = NULL;
698 available = pkg_vec_alloc();
699 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
700 pkg_vec_sort(available, pkg_compare_names);
701 for (i=0; i < available->len; i++) {
702 pkg = available->pkgs[i];
703 /* if we have package name or pattern and pkg does not match, then skip it */
704 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
709 pkg_vec_free(available);
714 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
716 struct active_list *head = prepare_upgrade_list(conf);
717 struct active_list *node=NULL;
718 pkg_t *_old_pkg, *_new_pkg;
720 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
721 _old_pkg = list_entry(node, pkg_t, list);
722 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
723 old_v = pkg_version_str_alloc(_old_pkg);
724 new_v = pkg_version_str_alloc(_new_pkg);
725 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
729 active_list_head_delete(head);
733 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
736 pkg_vec_t *available;
738 char *pkg_name = NULL;
744 available = pkg_vec_alloc();
746 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
748 pkg_hash_fetch_available(&conf->pkg_hash, available);
750 for (i=0; i < available->len; i++) {
751 pkg = available->pkgs[i];
752 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
756 pkg_formatted_info(stdout, pkg);
758 if (conf->verbosity >= OPKG_NOTICE) {
759 conffile_list_elt_t *iter;
760 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
761 conffile_t *cf = (conffile_t *)iter->data;
762 int modified = conffile_has_been_modified(conf, cf);
764 opkg_message(conf, OPKG_NOTICE,
765 "conffile=%s md5sum=%s modified=%d\n",
766 cf->name, cf->value, modified);
770 pkg_vec_free(available);
775 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
777 return opkg_info_status_cmd(conf, argc, argv, 0);
780 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
782 return opkg_info_status_cmd(conf, argc, argv, 1);
785 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
790 char *pkg_name = NULL;
794 err = opkg_configure_packages (conf, pkg_name);
797 err = opkg_configure_packages (conf, NULL);
800 write_status_files_if_changed(conf);
805 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
809 pkg_t *pkg_to_remove;
810 pkg_vec_t *available;
815 signal(SIGINT, sigint_handler);
817 pkg_info_preinstall_check(conf);
819 available = pkg_vec_alloc();
820 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
822 for (i=0; i<argc; i++) {
823 for (a=0; a<available->len; a++) {
824 pkg = available->pkgs[a];
825 if (fnmatch(argv[i], pkg->name, 0)) {
828 if (conf->restrict_to_default_dest) {
829 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
833 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
836 if (pkg_to_remove == NULL) {
837 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
840 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
841 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
844 opkg_remove_pkg(conf, pkg_to_remove, 0);
849 pkg_vec_free(available);
852 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
854 write_status_files_if_changed(conf);
858 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
864 signal(SIGINT, sigint_handler);
866 pkg_info_preinstall_check(conf);
868 for (i=0; i < argc; i++) {
869 if (conf->restrict_to_default_dest) {
870 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
874 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
878 opkg_message(conf, OPKG_ERROR,
879 "Package %s is not installed.\n", argv[i]);
882 opkg_purge_pkg(conf, pkg);
885 write_status_files_if_changed(conf);
889 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
893 const char *flags = argv[0];
896 signal(SIGINT, sigint_handler);
898 for (i=1; i < argc; i++) {
899 if (conf->restrict_to_default_dest) {
900 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
904 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
908 opkg_message(conf, OPKG_ERROR,
909 "Package %s is not installed.\n", argv[i]);
912 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
913 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
914 pkg->state_flag = pkg_state_flag_from_str(flags);
916 /* pb_ asked this feature 03292004 */
917 /* Actually I will use only this two, but this is an open for various status */
918 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
919 pkg->state_status = pkg_state_status_from_str(flags);
921 opkg_state_changed++;
922 opkg_message(conf, OPKG_NOTICE,
923 "Setting flags for package %s to %s\n",
927 write_status_files_if_changed(conf);
931 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
935 str_list_elt_t *iter;
942 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
945 opkg_message(conf, OPKG_ERROR,
946 "Package %s not installed.\n", argv[0]);
950 files = pkg_get_installed_files(conf, pkg);
951 pkg_version = pkg_version_str_alloc(pkg);
953 printf("Package %s (%s) is installed on %s and has the following files:\n",
954 pkg->name, pkg_version, pkg->dest->name);
956 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
957 printf("%s\n", (char *)iter->data);
960 pkg_free_installed_files(pkg);
965 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
969 pkg_vec_t *available_pkgs = pkg_vec_alloc();
970 const char *rel_str = "depends on";
973 pkg_info_preinstall_check(conf);
976 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
978 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
979 for (i = 0; i < argc; i++) {
980 const char *target = argv[i];
983 opkg_message(conf, OPKG_NOTICE, "target=%s\n", target);
985 for (j = 0; j < available_pkgs->len; j++) {
986 pkg_t *pkg = available_pkgs->pkgs[j];
987 if (fnmatch(target, pkg->name, 0) == 0) {
989 int count = pkg->depends_count + pkg->pre_depends_count;
990 opkg_message(conf, OPKG_NOTICE, "What %s (arch=%s) %s\n",
991 target, pkg->architecture, rel_str);
992 for (k = 0; k < count; k++) {
993 compound_depend_t *cdepend = &pkg->depends[k];
995 for (l = 0; l < cdepend->possibility_count; l++) {
996 depend_t *possibility = cdepend->possibilities[l];
997 opkg_message(conf, OPKG_NOTICE, " %s", possibility->pkg->name);
998 if (conf->verbosity >= OPKG_NOTICE) {
999 if (possibility->version) {
1000 char *typestr = NULL;
1001 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1002 switch (possibility->constraint) {
1003 case NONE: typestr = "none"; break;
1004 case EARLIER: typestr = "<"; break;
1005 case EARLIER_EQUAL: typestr = "<="; break;
1006 case EQUAL: typestr = "="; break;
1007 case LATER_EQUAL: typestr = ">="; break;
1008 case LATER: typestr = ">"; break;
1010 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1013 opkg_message(conf, OPKG_NOTICE, "\n");
1019 pkg_vec_free(available_pkgs);
1024 enum what_field_type {
1033 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum depend_type what_field_type, int recursive, int argc, char **argv)
1037 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1038 const char *rel_str = NULL;
1042 switch (what_field_type) {
1043 case DEPEND: rel_str = "depends on"; break;
1044 case CONFLICTS: rel_str = "conflicts with"; break;
1045 case SUGGEST: rel_str = "suggests"; break;
1046 case RECOMMEND: rel_str = "recommends"; break;
1050 if (conf->query_all)
1051 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1053 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1055 /* mark the root set */
1056 pkg_vec_clear_marks(available_pkgs);
1057 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1058 for (i = 0; i < argc; i++) {
1059 const char *dependee_pattern = argv[i];
1060 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1062 for (i = 0; i < available_pkgs->len; i++) {
1063 pkg_t *pkg = available_pkgs->pkgs[i];
1064 if (pkg->state_flag & SF_MARKED) {
1065 /* mark the parent (abstract) package */
1066 pkg_mark_provides(pkg);
1067 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1071 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1076 for (j = 0; j < available_pkgs->len; j++) {
1077 pkg_t *pkg = available_pkgs->pkgs[j];
1079 int count = ((what_field_type == CONFLICTS)
1080 ? pkg->conflicts_count
1081 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1082 /* skip this package if it is already marked */
1083 if (pkg->parent->state_flag & SF_MARKED) {
1086 for (k = 0; k < count; k++) {
1087 compound_depend_t *cdepend =
1088 (what_field_type == CONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1090 if (what_field_type != cdepend->type)
1092 for (l = 0; l < cdepend->possibility_count; l++) {
1093 depend_t *possibility = cdepend->possibilities[l];
1094 if (possibility->pkg->state_flag & SF_MARKED) {
1095 /* mark the depending package so we won't visit it again */
1096 pkg->state_flag |= SF_MARKED;
1097 pkg_mark_provides(pkg);
1100 if (conf->verbosity >= OPKG_NOTICE) {
1101 char *ver = pkg_version_str_alloc(pkg);
1102 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1103 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1104 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1105 if (possibility->version) {
1106 char *typestr = NULL;
1107 switch (possibility->constraint) {
1108 case NONE: typestr = "none"; break;
1109 case EARLIER: typestr = "<"; break;
1110 case EARLIER_EQUAL: typestr = "<="; break;
1111 case EQUAL: typestr = "="; break;
1112 case LATER_EQUAL: typestr = ">="; break;
1113 case LATER: typestr = ">"; break;
1115 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1118 if (!pkg_dependence_satisfiable(conf, possibility))
1119 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1121 opkg_message(conf, OPKG_NOTICE, "\n");
1129 } while (changed && recursive);
1130 pkg_vec_free(available_pkgs);
1136 static int pkg_mark_provides(pkg_t *pkg)
1138 int provides_count = pkg->provides_count;
1139 abstract_pkg_t **provides = pkg->provides;
1141 pkg->parent->state_flag |= SF_MARKED;
1142 for (i = 0; i < provides_count; i++) {
1143 provides[i]->state_flag |= SF_MARKED;
1148 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1150 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 1, argc, argv);
1152 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1154 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 0, argc, argv);
1157 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1159 return opkg_what_depends_conflicts_cmd(conf, SUGGEST, 0, argc, argv);
1162 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1164 return opkg_what_depends_conflicts_cmd(conf, RECOMMEND, 0, argc, argv);
1167 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1169 return opkg_what_depends_conflicts_cmd(conf, CONFLICTS, 0, argc, argv);
1172 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1176 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1177 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1180 pkg_info_preinstall_check(conf);
1182 if (conf->query_all)
1183 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1185 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1186 for (i = 0; i < argc; i++) {
1187 const char *target = argv[i];
1190 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1192 for (j = 0; j < available_pkgs->len; j++) {
1193 pkg_t *pkg = available_pkgs->pkgs[j];
1195 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1196 for (k = 0; k < count; k++) {
1197 abstract_pkg_t *apkg =
1198 ((what_field_type == WHATPROVIDES)
1200 : pkg->replaces[k]);
1201 if (fnmatch(target, apkg->name, 0) == 0) {
1202 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1203 if (strcmp(target, apkg->name) != 0)
1204 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1205 opkg_message(conf, OPKG_ERROR, "\n");
1210 pkg_vec_free(available_pkgs);
1215 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1217 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1220 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1222 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1225 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1229 pkg_vec_t *installed;
1231 str_list_t *installed_files;
1232 str_list_elt_t *iter;
1233 char *installed_file;
1239 installed = pkg_vec_alloc();
1240 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1241 pkg_vec_sort(installed, pkg_compare_names);
1243 for (i=0; i < installed->len; i++) {
1244 pkg = installed->pkgs[i];
1246 installed_files = pkg_get_installed_files(conf, pkg);
1248 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1249 installed_file = (char *)iter->data;
1250 if (fnmatch(argv[0], installed_file, 0)==0)
1254 pkg_free_installed_files(pkg);
1257 pkg_vec_free(installed);
1262 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1265 /* this is a bit gross */
1267 parse_version(&p1, argv[0]);
1268 parse_version(&p2, argv[2]);
1269 return pkg_version_satisfied(&p1, &p2, argv[1]);
1271 opkg_message(conf, OPKG_ERROR,
1272 "opkg compare_versions <v1> <op> <v2>\n"
1273 "<op> is one of <= >= << >> =\n");
1278 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1280 nv_pair_list_elt_t *l;
1282 list_for_each_entry(l, &conf->arch_list.head, node) {
1283 nv_pair_t *nv = (nv_pair_t *)l->data;
1284 printf("arch %s %s\n", nv->name, nv->value);