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.
23 #include "opkg_conf.h"
25 #include "opkg_message.h"
28 #include "pkg_parse.h"
29 #include "sprintf_alloc.h"
31 #include "file_util.h"
33 #include "libbb/libbb.h"
34 #include "opkg_utils.h"
35 #include "opkg_defines.h"
40 #include "opkg_download.h"
41 #include "opkg_install.h"
42 #include "opkg_upgrade.h"
43 #include "opkg_remove.h"
44 #include "opkg_configure.h"
45 #include "opkg_message.h"
49 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv);
50 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv);
51 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv);
52 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv);
53 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv);
54 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv);
55 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv);
56 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv);
57 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv);
58 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
70 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
71 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
72 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
73 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
74 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
75 static int pkg_mark_provides(pkg_t *pkg);
77 /* XXX: CLEANUP: The usage strings should be incorporated into this
78 array for easier maintenance */
79 static opkg_cmd_t cmds[] = {
80 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
81 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
82 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
83 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
84 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
85 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
86 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
87 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
88 {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd},
89 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
90 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
91 {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
92 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
93 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
94 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
95 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
96 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
97 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
98 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
99 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
100 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
101 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
102 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
103 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
104 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
105 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
106 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
107 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
108 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
109 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
112 static void print_pkg(pkg_t *pkg)
114 char *version = pkg_version_str_alloc(pkg);
115 if (pkg->description)
116 printf("%s - %s - %s\n", pkg->name, version, pkg->description);
118 printf("%s - %s\n", pkg->name, version);
122 int opkg_state_changed;
123 static void write_status_files_if_changed(opkg_conf_t *conf)
125 if (opkg_state_changed && !conf->noaction) {
126 opkg_message(conf, OPKG_INFO,
127 " writing status file\n");
128 opkg_conf_write_status_files(conf);
129 pkg_write_changed_filelists(conf);
131 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
136 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
138 opkg_cmd_t *opkg_cmd_find(const char *name)
143 for (i=0; i < num_cmds; i++) {
145 if (strcmp(name, cmd->name) == 0) {
153 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
157 result = (cmd->fun)(conf, argc, argv);
165 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
171 pkg_src_list_elt_t *iter;
175 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
177 if (! file_is_dir(lists_dir)) {
178 if (file_exists(lists_dir)) {
179 opkg_message(conf, OPKG_ERROR,
180 "%s: ERROR: %s exists, but is not a directory\n",
181 __FUNCTION__, lists_dir);
185 err = file_mkdir_hier(lists_dir, 0755);
187 opkg_message(conf, OPKG_ERROR,
188 "%s: ERROR: failed to make directory %s: %s\n",
189 __FUNCTION__, lists_dir, strerror(errno));
198 tmp = strdup ("/tmp/opkg.XXXXXX");
200 if (mkdtemp (tmp) == NULL) {
206 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
207 char *url, *list_file_name;
209 src = (pkg_src_t *)iter->data;
211 if (src->extra_data) /* debian style? */
212 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
213 src->gzip ? "Packages.gz" : "Packages");
215 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
217 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
222 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
223 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
225 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
226 in = fopen (tmp_file_name, "r");
227 out = fopen (list_file_name, "w");
236 unlink (tmp_file_name);
240 err = opkg_download(conf, url, list_file_name, NULL, NULL);
244 opkg_message(conf, OPKG_NOTICE,
245 "Updated list of available packages in %s\n",
249 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
250 if (conf->check_signature) {
251 /* download detached signitures to verify the package lists */
252 /* get the url for the sig file */
253 if (src->extra_data) /* debian style? */
254 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
257 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
259 /* create temporary file for it */
262 /* Put the signature in the right place */
263 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
265 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
268 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
271 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
273 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
275 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
277 /* We shouldn't unlink the signature ! */
278 // unlink (tmp_file_name);
279 free (tmp_file_name);
285 free(list_file_name);
295 struct opkg_intercept
301 typedef struct opkg_intercept *opkg_intercept_t;
303 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
305 opkg_intercept_t ctx;
310 ctx = calloc (1, sizeof (*ctx));
311 oldpath = getenv ("PATH");
313 ctx->oldpath = strdup (oldpath);
319 sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
320 setenv ("PATH", newpath, 1);
325 sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
326 if (mkdir (ctx->statedir, 0770) < 0) {
327 if (errno == EEXIST) {
328 free (ctx->statedir);
332 perror (ctx->statedir);
335 setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
339 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
346 setenv ("PATH", ctx->oldpath, 1);
352 dir = opendir (ctx->statedir);
355 while (de = readdir (dir), de != NULL) {
358 if (de->d_name[0] == '.')
361 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
362 if (access (path, X_OK) == 0) {
372 perror (ctx->statedir);
374 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
378 free (ctx->statedir);
384 /* For package pkg do the following: If it is already visited, return. If not,
385 add it in visited list and recurse to its deps. Finally, add it to ordered
387 pkg_vec all contains all available packages in repos.
388 pkg_vec visited contains packages already visited by this function, and is
389 used to end recursion and avoid an infinite loop on graph cycles.
390 pkg_vec ordered will finally contain the ordered set of packages.
392 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
393 pkg_vec_t *visited, pkg_vec_t *ordered)
398 compound_depend_t * compound_depend;
399 depend_t ** possible_satisfiers;
400 abstract_pkg_t *abpkg;
401 abstract_pkg_t **dependents;
403 /* If it's just an available package, that is, not installed and not even
405 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
406 would do here. However, if there is an intermediate node (pkg) that is
407 configured and installed between two unpacked packages, the latter
408 won't be properly reordered, unless all installed/unpacked pkgs are
410 if (pkg->state_status == SS_NOT_INSTALLED)
413 /* If the package has already been visited (by this function), skip it */
414 for(j = 0; j < visited->len; j++)
415 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
416 opkg_message(conf, OPKG_INFO,
417 " pkg: %s already visited\n", pkg->name);
421 pkg_vec_insert(visited, pkg);
423 count = pkg->pre_depends_count + pkg->depends_count + \
424 pkg->recommends_count + pkg->suggests_count;
426 opkg_message(conf, OPKG_INFO,
427 " pkg: %s\n", pkg->name);
429 /* Iterate over all the dependencies of pkg. For each one, find a package
430 that is either installed or unpacked and satisfies this dependency.
431 (there should only be one such package per dependency installed or
432 unpacked). Then recurse to the dependency package */
433 for (j=0; j < count ; j++) {
434 compound_depend = &pkg->depends[j];
435 possible_satisfiers = compound_depend->possibilities;
436 for (k=0; k < compound_depend->possibility_count ; k++) {
437 abpkg = possible_satisfiers[k]->pkg;
438 dependents = abpkg->provided_by->pkgs;
440 if (dependents != NULL)
441 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
442 opkg_message(conf, OPKG_INFO,
443 " Descending on pkg: %s\n",
444 dependents [l]->name);
446 /* find whether dependent l is installed or unpacked,
447 * and then find which package in the list satisfies it */
448 for(m = 0; m < all->len; m++) {
450 if ( dep->state_status != SS_NOT_INSTALLED)
451 if ( ! strcmp(dep->name, dependents[l]->name)) {
452 opkg_recurse_pkgs_in_order(conf, dep, all,
454 /* Stop the outer loop */
455 l = abpkg->provided_by->len;
456 /* break from the inner loop */
465 /* When all recursions from this node down, are over, and all
466 dependencies have been added in proper order in the ordered array, add
467 also the package pkg to ordered array */
468 pkg_vec_insert(ordered, pkg);
474 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
476 pkg_vec_t *all, *ordered, *visited;
482 opkg_message(conf, OPKG_INFO,
483 "Configuring unpacked packages\n");
486 all = pkg_vec_alloc();
488 pkg_hash_fetch_available(&conf->pkg_hash, all);
490 /* Reorder pkgs in order to be configured according to the Depends: tag
492 opkg_message(conf, OPKG_INFO,
493 "Reordering packages before configuring them...\n");
494 ordered = pkg_vec_alloc();
495 visited = pkg_vec_alloc();
496 for(i = 0; i < all->len; i++) {
498 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
502 ic = opkg_prep_intercepts (conf);
504 for(i = 0; i < all->len; i++) {
507 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
510 if (pkg->state_status == SS_UNPACKED) {
511 opkg_message(conf, OPKG_NOTICE,
512 "Configuring %s\n", pkg->name);
514 r = opkg_configure(conf, pkg);
516 pkg->state_status = SS_INSTALLED;
517 pkg->parent->state_status = SS_INSTALLED;
518 pkg->state_flag &= ~SF_PREFER;
526 r = opkg_finalize_intercepts (ic);
531 pkg_vec_free(ordered);
532 pkg_vec_free(visited);
537 static opkg_conf_t *global_conf;
539 static void sigint_handler(int sig)
541 signal(sig, SIG_DFL);
542 opkg_message(NULL, OPKG_NOTICE,
543 "opkg: interrupted. writing out status database\n");
544 write_status_files_if_changed(global_conf);
548 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
555 signal(SIGINT, sigint_handler);
558 * Now scan through package names and install
560 for (i=0; i < argc; i++) {
563 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
564 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
565 if (err != EINVAL && err != 0)
568 pkg_info_preinstall_check(conf);
570 for (i=0; i < argc; i++) {
572 err = opkg_install_by_name(conf, arg);
573 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
574 opkg_message(conf, OPKG_ERROR,
575 "Cannot find package %s.\n",
580 /* recheck to verify that all dependences are satisfied */
581 if (0) opkg_satisfy_all_dependences(conf);
583 opkg_configure_packages(conf, NULL);
585 write_status_files_if_changed(conf);
590 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
597 signal(SIGINT, sigint_handler);
600 for (i=0; i < argc; i++) {
603 err = opkg_prepare_url_for_install(conf, arg, &arg);
604 if (err != EINVAL && err != 0)
607 pkg_info_preinstall_check(conf);
609 for (i=0; i < argc; i++) {
611 if (conf->restrict_to_default_dest) {
612 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
616 opkg_message(conf, OPKG_NOTICE,
617 "Package %s not installed in %s\n",
618 argv[i], conf->default_dest->name);
622 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
626 opkg_upgrade_pkg(conf, pkg);
628 opkg_install_by_name(conf, arg);
632 pkg_vec_t *installed = pkg_vec_alloc();
634 pkg_info_preinstall_check(conf);
636 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
637 for (i = 0; i < installed->len; i++) {
638 pkg = installed->pkgs[i];
639 opkg_upgrade_pkg(conf, pkg);
641 pkg_vec_free(installed);
644 /* recheck to verify that all dependences are satisfied */
645 if (0) opkg_satisfy_all_dependences(conf);
647 opkg_configure_packages(conf, NULL);
649 write_status_files_if_changed(conf);
654 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
660 pkg_info_preinstall_check(conf);
661 for (i = 0; i < argc; i++) {
664 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
666 opkg_message(conf, OPKG_ERROR,
667 "Cannot find package %s.\n"
668 "Check the spelling or perhaps run 'opkg update'\n",
673 err = opkg_download_pkg(conf, pkg, ".");
676 opkg_message(conf, OPKG_ERROR,
677 "Failed to download %s\n", pkg->name);
679 opkg_message(conf, OPKG_NOTICE,
680 "Downloaded %s as %s\n",
681 pkg->name, pkg->local_filename);
689 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
692 pkg_vec_t *available;
694 char *pkg_name = NULL;
699 available = pkg_vec_alloc();
700 pkg_hash_fetch_available(&conf->pkg_hash, available);
701 pkg_vec_sort(available, pkg_compare_names);
702 for (i=0; i < available->len; i++) {
703 pkg = available->pkgs[i];
704 /* if we have package name or pattern and pkg does not match, then skip it */
705 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
709 pkg_vec_free(available);
715 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
718 pkg_vec_t *available;
720 char *pkg_name = NULL;
725 available = pkg_vec_alloc();
726 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
727 pkg_vec_sort(available, pkg_compare_names);
728 for (i=0; i < available->len; i++) {
729 pkg = available->pkgs[i];
730 /* if we have package name or pattern and pkg does not match, then skip it */
731 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
736 pkg_vec_free(available);
741 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
743 struct active_list *head = prepare_upgrade_list(conf);
744 struct active_list *node=NULL;
745 pkg_t *_old_pkg, *_new_pkg;
747 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
748 _old_pkg = list_entry(node, pkg_t, list);
749 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
750 old_v = pkg_version_str_alloc(_old_pkg);
751 new_v = pkg_version_str_alloc(_new_pkg);
752 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
756 active_list_head_delete(head);
760 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
763 pkg_vec_t *available;
765 char *pkg_name = NULL;
771 available = pkg_vec_alloc();
773 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
775 pkg_hash_fetch_available(&conf->pkg_hash, available);
777 for (i=0; i < available->len; i++) {
778 pkg = available->pkgs[i];
779 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
783 pkg_formatted_info(stdout, pkg);
785 if (conf->verbosity > 1) {
786 conffile_list_elt_t *iter;
787 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
788 conffile_t *cf = (conffile_t *)iter->data;
789 int modified = conffile_has_been_modified(conf, cf);
790 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
791 cf->name, cf->value, modified);
795 pkg_vec_free(available);
800 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
802 return opkg_info_status_cmd(conf, argc, argv, 0);
805 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
807 return opkg_info_status_cmd(conf, argc, argv, 1);
810 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
815 char *pkg_name = NULL;
819 err = opkg_configure_packages (conf, pkg_name);
822 err = opkg_configure_packages (conf, NULL);
825 write_status_files_if_changed(conf);
830 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
836 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
837 err = glob(globpattern, 0, NULL, &globbuf);
843 opkg_message(conf, OPKG_NOTICE,
844 "The following packages in %s will now be installed.\n",
846 for (i = 0; i < globbuf.gl_pathc; i++) {
847 opkg_message(conf, OPKG_NOTICE,
848 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
850 opkg_message(conf, OPKG_NOTICE, "\n");
851 for (i = 0; i < globbuf.gl_pathc; i++) {
852 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
854 err = unlink(globbuf.gl_pathv[i]);
856 opkg_message(conf, OPKG_ERROR,
857 "%s: ERROR: failed to unlink %s: %s\n",
858 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
868 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
872 pkg_t *pkg_to_remove;
873 pkg_vec_t *available;
874 char *pkg_name = NULL;
876 signal(SIGINT, sigint_handler);
878 // ENH: Add the "no pkg removed" just in case.
882 pkg_info_preinstall_check(conf);
884 available = pkg_vec_alloc();
885 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
886 for (i=0; i < argc; i++) {
887 pkg_name = calloc(1, strlen(argv[i])+2);
888 strcpy(pkg_name,argv[i]);
889 for (a=0; a < available->len; a++) {
890 pkg = available->pkgs[a];
891 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
894 if (conf->restrict_to_default_dest) {
895 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
899 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
902 if (pkg_to_remove == NULL) {
903 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
906 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
907 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
910 opkg_remove_pkg(conf, pkg_to_remove,0);
915 pkg_vec_free(available);
917 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
919 int flagged_pkg_count = 0;
922 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
924 for (i = 0; i < installed_pkgs->len; i++) {
925 pkg_t *pkg = installed_pkgs->pkgs[i];
926 if (pkg->state_flag & SF_USER) {
929 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
930 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
933 if (!flagged_pkg_count) {
934 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
935 "so refusing to uninstall unflagged non-leaf packages\n");
939 /* find packages not flagged SF_USER (i.e., installed to
940 * satisfy a dependence) and not having any dependents, and
944 for (i = 0; i < installed_pkgs->len; i++) {
945 pkg_t *pkg = installed_pkgs->pkgs[i];
946 if (!(pkg->state_flag & SF_USER)
947 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
949 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
950 opkg_remove_pkg(conf, pkg,0);
955 pkg_vec_free(installed_pkgs);
959 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
961 write_status_files_if_changed(conf);
965 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
971 signal(SIGINT, sigint_handler);
973 pkg_info_preinstall_check(conf);
975 for (i=0; i < argc; i++) {
976 if (conf->restrict_to_default_dest) {
977 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
981 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
985 opkg_message(conf, OPKG_ERROR,
986 "Package %s is not installed.\n", argv[i]);
989 opkg_purge_pkg(conf, pkg);
992 write_status_files_if_changed(conf);
996 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1000 const char *flags = argv[0];
1003 signal(SIGINT, sigint_handler);
1005 for (i=1; i < argc; i++) {
1006 if (conf->restrict_to_default_dest) {
1007 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1009 conf->default_dest);
1011 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1015 opkg_message(conf, OPKG_ERROR,
1016 "Package %s is not installed.\n", argv[i]);
1019 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1020 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1021 pkg->state_flag = pkg_state_flag_from_str(flags);
1023 /* pb_ asked this feature 03292004 */
1024 /* Actually I will use only this two, but this is an open for various status */
1025 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1026 pkg->state_status = pkg_state_status_from_str(flags);
1028 opkg_state_changed++;
1029 opkg_message(conf, OPKG_NOTICE,
1030 "Setting flags for package %s to %s\n",
1034 write_status_files_if_changed(conf);
1038 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1042 str_list_elt_t *iter;
1049 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1052 opkg_message(conf, OPKG_ERROR,
1053 "Package %s not installed.\n", argv[0]);
1057 files = pkg_get_installed_files(pkg);
1058 pkg_version = pkg_version_str_alloc(pkg);
1060 printf("Package %s (%s) is installed on %s and has the following files:\n",
1061 pkg->name, pkg_version, pkg->dest->name);
1063 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
1064 printf("%s\n", (char *)iter->data);
1067 pkg_free_installed_files(pkg);
1072 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1076 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1077 const char *rel_str = "depends on";
1080 pkg_info_preinstall_check(conf);
1082 if (conf->query_all)
1083 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1085 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1086 for (i = 0; i < argc; i++) {
1087 const char *target = argv[i];
1090 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1092 for (j = 0; j < available_pkgs->len; j++) {
1093 pkg_t *pkg = available_pkgs->pkgs[j];
1094 if (fnmatch(target, pkg->name, 0) == 0) {
1096 int count = pkg->depends_count + pkg->pre_depends_count;
1097 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1098 target, pkg->architecture, rel_str);
1099 for (k = 0; k < count; k++) {
1100 compound_depend_t *cdepend = &pkg->depends[k];
1102 for (l = 0; l < cdepend->possibility_count; l++) {
1103 depend_t *possibility = cdepend->possibilities[l];
1104 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1105 if (conf->verbosity > 0) {
1106 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1107 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1108 if (possibility->version) {
1109 char *typestr = NULL;
1110 switch (possibility->constraint) {
1111 case NONE: typestr = "none"; break;
1112 case EARLIER: typestr = "<"; break;
1113 case EARLIER_EQUAL: typestr = "<="; break;
1114 case EQUAL: typestr = "="; break;
1115 case LATER_EQUAL: typestr = ">="; break;
1116 case LATER: typestr = ">"; break;
1118 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1122 opkg_message(conf, OPKG_ERROR, "\n");
1128 pkg_vec_free(available_pkgs);
1133 enum what_field_type {
1142 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1146 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1147 const char *rel_str = NULL;
1151 switch (what_field_type) {
1152 case WHATDEPENDS: rel_str = "depends on"; break;
1153 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1154 case WHATSUGGESTS: rel_str = "suggests"; break;
1155 case WHATRECOMMENDS: rel_str = "recommends"; break;
1156 case WHATPROVIDES: rel_str = "provides"; break;
1157 case WHATREPLACES: rel_str = "replaces"; break;
1160 if (conf->query_all)
1161 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1163 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1165 /* mark the root set */
1166 pkg_vec_clear_marks(available_pkgs);
1167 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1168 for (i = 0; i < argc; i++) {
1169 const char *dependee_pattern = argv[i];
1170 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1172 for (i = 0; i < available_pkgs->len; i++) {
1173 pkg_t *pkg = available_pkgs->pkgs[i];
1174 if (pkg->state_flag & SF_MARKED) {
1175 /* mark the parent (abstract) package */
1176 pkg_mark_provides(pkg);
1177 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1181 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1186 for (j = 0; j < available_pkgs->len; j++) {
1187 pkg_t *pkg = available_pkgs->pkgs[j];
1189 int count = ((what_field_type == WHATCONFLICTS)
1190 ? pkg->conflicts_count
1191 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1192 /* skip this package if it is already marked */
1193 if (pkg->parent->state_flag & SF_MARKED) {
1196 for (k = 0; k < count; k++) {
1197 compound_depend_t *cdepend =
1198 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1200 for (l = 0; l < cdepend->possibility_count; l++) {
1201 depend_t *possibility = cdepend->possibilities[l];
1202 if (possibility->pkg->state_flag & SF_MARKED) {
1203 /* mark the depending package so we won't visit it again */
1204 pkg->state_flag |= SF_MARKED;
1205 pkg_mark_provides(pkg);
1208 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1209 if (conf->verbosity > 0) {
1210 char *ver = pkg_version_str_alloc(pkg);
1211 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1212 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1213 if (possibility->version) {
1214 char *typestr = NULL;
1215 switch (possibility->constraint) {
1216 case NONE: typestr = "none"; break;
1217 case EARLIER: typestr = "<"; break;
1218 case EARLIER_EQUAL: typestr = "<="; break;
1219 case EQUAL: typestr = "="; break;
1220 case LATER_EQUAL: typestr = ">="; break;
1221 case LATER: typestr = ">"; break;
1223 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1226 if (!pkg_dependence_satisfiable(conf, possibility))
1227 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1229 opkg_message(conf, OPKG_NOTICE, "\n");
1237 } while (changed && recursive);
1238 pkg_vec_free(available_pkgs);
1244 static int pkg_mark_provides(pkg_t *pkg)
1246 int provides_count = pkg->provides_count;
1247 abstract_pkg_t **provides = pkg->provides;
1249 pkg->parent->state_flag |= SF_MARKED;
1250 for (i = 0; i < provides_count; i++) {
1251 provides[i]->state_flag |= SF_MARKED;
1256 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1258 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1260 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1262 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1265 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1267 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1270 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1272 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1275 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1277 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1280 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1284 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1285 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1288 pkg_info_preinstall_check(conf);
1290 if (conf->query_all)
1291 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1293 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1294 for (i = 0; i < argc; i++) {
1295 const char *target = argv[i];
1298 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1300 for (j = 0; j < available_pkgs->len; j++) {
1301 pkg_t *pkg = available_pkgs->pkgs[j];
1303 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1304 for (k = 0; k < count; k++) {
1305 abstract_pkg_t *apkg =
1306 ((what_field_type == WHATPROVIDES)
1308 : pkg->replaces[k]);
1309 if (fnmatch(target, apkg->name, 0) == 0) {
1310 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1311 if (strcmp(target, apkg->name) != 0)
1312 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1313 opkg_message(conf, OPKG_ERROR, "\n");
1318 pkg_vec_free(available_pkgs);
1323 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1325 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1328 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1330 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1333 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1337 pkg_vec_t *installed;
1339 str_list_t *installed_files;
1340 str_list_elt_t *iter;
1341 char *installed_file;
1347 installed = pkg_vec_alloc();
1348 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1349 pkg_vec_sort(installed, pkg_compare_names);
1351 for (i=0; i < installed->len; i++) {
1352 pkg = installed->pkgs[i];
1354 installed_files = pkg_get_installed_files(pkg);
1356 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1357 installed_file = (char *)iter->data;
1358 if (fnmatch(argv[0], installed_file, 0)==0)
1362 pkg_free_installed_files(pkg);
1365 pkg_vec_free(installed);
1370 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1373 /* this is a bit gross */
1375 parseVersion(&p1, argv[0]);
1376 parseVersion(&p2, argv[2]);
1377 return pkg_version_satisfied(&p1, &p2, argv[1]);
1379 opkg_message(conf, OPKG_ERROR,
1380 "opkg compare_versions <v1> <op> <v2>\n"
1381 "<op> is one of <= >= << >> =\n");
1386 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1388 nv_pair_list_elt_t *l;
1390 list_for_each_entry(l, &conf->arch_list.head, node) {
1391 nv_pair_t *nv = (nv_pair_t *)l->data;
1392 printf("arch %s %s\n", nv->name, nv->value);