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 = xstrdup("/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;
309 ctx = calloc (1, sizeof (*ctx));
310 ctx->oldpath = xstrdup(getenv("PATH"));
312 sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
313 setenv ("PATH", newpath, 1);
318 sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
319 if (mkdir (ctx->statedir, 0770) < 0) {
320 if (errno == EEXIST) {
321 free (ctx->statedir);
325 perror (ctx->statedir);
328 setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
332 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
339 setenv ("PATH", ctx->oldpath, 1);
345 dir = opendir (ctx->statedir);
348 while (de = readdir (dir), de != NULL) {
351 if (de->d_name[0] == '.')
354 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
355 if (access (path, X_OK) == 0) {
365 perror (ctx->statedir);
367 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
371 free (ctx->statedir);
377 /* For package pkg do the following: If it is already visited, return. If not,
378 add it in visited list and recurse to its deps. Finally, add it to ordered
380 pkg_vec all contains all available packages in repos.
381 pkg_vec visited contains packages already visited by this function, and is
382 used to end recursion and avoid an infinite loop on graph cycles.
383 pkg_vec ordered will finally contain the ordered set of packages.
385 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
386 pkg_vec_t *visited, pkg_vec_t *ordered)
391 compound_depend_t * compound_depend;
392 depend_t ** possible_satisfiers;
393 abstract_pkg_t *abpkg;
394 abstract_pkg_t **dependents;
396 /* If it's just an available package, that is, not installed and not even
398 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
399 would do here. However, if there is an intermediate node (pkg) that is
400 configured and installed between two unpacked packages, the latter
401 won't be properly reordered, unless all installed/unpacked pkgs are
403 if (pkg->state_status == SS_NOT_INSTALLED)
406 /* If the package has already been visited (by this function), skip it */
407 for(j = 0; j < visited->len; j++)
408 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
409 opkg_message(conf, OPKG_INFO,
410 " pkg: %s already visited\n", pkg->name);
414 pkg_vec_insert(visited, pkg);
416 count = pkg->pre_depends_count + pkg->depends_count + \
417 pkg->recommends_count + pkg->suggests_count;
419 opkg_message(conf, OPKG_INFO,
420 " pkg: %s\n", pkg->name);
422 /* Iterate over all the dependencies of pkg. For each one, find a package
423 that is either installed or unpacked and satisfies this dependency.
424 (there should only be one such package per dependency installed or
425 unpacked). Then recurse to the dependency package */
426 for (j=0; j < count ; j++) {
427 compound_depend = &pkg->depends[j];
428 possible_satisfiers = compound_depend->possibilities;
429 for (k=0; k < compound_depend->possibility_count ; k++) {
430 abpkg = possible_satisfiers[k]->pkg;
431 dependents = abpkg->provided_by->pkgs;
433 if (dependents != NULL)
434 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
435 opkg_message(conf, OPKG_INFO,
436 " Descending on pkg: %s\n",
437 dependents [l]->name);
439 /* find whether dependent l is installed or unpacked,
440 * and then find which package in the list satisfies it */
441 for(m = 0; m < all->len; m++) {
443 if ( dep->state_status != SS_NOT_INSTALLED)
444 if ( ! strcmp(dep->name, dependents[l]->name)) {
445 opkg_recurse_pkgs_in_order(conf, dep, all,
447 /* Stop the outer loop */
448 l = abpkg->provided_by->len;
449 /* break from the inner loop */
458 /* When all recursions from this node down, are over, and all
459 dependencies have been added in proper order in the ordered array, add
460 also the package pkg to ordered array */
461 pkg_vec_insert(ordered, pkg);
467 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
469 pkg_vec_t *all, *ordered, *visited;
475 opkg_message(conf, OPKG_INFO,
476 "Configuring unpacked packages\n");
479 all = pkg_vec_alloc();
481 pkg_hash_fetch_available(&conf->pkg_hash, all);
483 /* Reorder pkgs in order to be configured according to the Depends: tag
485 opkg_message(conf, OPKG_INFO,
486 "Reordering packages before configuring them...\n");
487 ordered = pkg_vec_alloc();
488 visited = pkg_vec_alloc();
489 for(i = 0; i < all->len; i++) {
491 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
495 ic = opkg_prep_intercepts (conf);
497 for(i = 0; i < all->len; i++) {
500 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
503 if (pkg->state_status == SS_UNPACKED) {
504 opkg_message(conf, OPKG_NOTICE,
505 "Configuring %s\n", pkg->name);
507 r = opkg_configure(conf, pkg);
509 pkg->state_status = SS_INSTALLED;
510 pkg->parent->state_status = SS_INSTALLED;
511 pkg->state_flag &= ~SF_PREFER;
519 r = opkg_finalize_intercepts (ic);
524 pkg_vec_free(ordered);
525 pkg_vec_free(visited);
530 static opkg_conf_t *global_conf;
532 static void sigint_handler(int sig)
534 signal(sig, SIG_DFL);
535 opkg_message(NULL, OPKG_NOTICE,
536 "opkg: interrupted. writing out status database\n");
537 write_status_files_if_changed(global_conf);
541 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
548 signal(SIGINT, sigint_handler);
551 * Now scan through package names and install
553 for (i=0; i < argc; i++) {
556 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
557 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
558 if (err != EINVAL && err != 0)
561 pkg_info_preinstall_check(conf);
563 for (i=0; i < argc; i++) {
565 err = opkg_install_by_name(conf, arg);
566 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
567 opkg_message(conf, OPKG_ERROR,
568 "Cannot find package %s.\n",
573 /* recheck to verify that all dependences are satisfied */
574 if (0) opkg_satisfy_all_dependences(conf);
576 opkg_configure_packages(conf, NULL);
578 write_status_files_if_changed(conf);
583 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
590 signal(SIGINT, sigint_handler);
593 for (i=0; i < argc; i++) {
596 err = opkg_prepare_url_for_install(conf, arg, &arg);
597 if (err != EINVAL && err != 0)
600 pkg_info_preinstall_check(conf);
602 for (i=0; i < argc; i++) {
604 if (conf->restrict_to_default_dest) {
605 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
609 opkg_message(conf, OPKG_NOTICE,
610 "Package %s not installed in %s\n",
611 argv[i], conf->default_dest->name);
615 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
619 opkg_upgrade_pkg(conf, pkg);
621 opkg_install_by_name(conf, arg);
625 pkg_vec_t *installed = pkg_vec_alloc();
627 pkg_info_preinstall_check(conf);
629 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
630 for (i = 0; i < installed->len; i++) {
631 pkg = installed->pkgs[i];
632 opkg_upgrade_pkg(conf, pkg);
634 pkg_vec_free(installed);
637 /* recheck to verify that all dependences are satisfied */
638 if (0) opkg_satisfy_all_dependences(conf);
640 opkg_configure_packages(conf, NULL);
642 write_status_files_if_changed(conf);
647 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
653 pkg_info_preinstall_check(conf);
654 for (i = 0; i < argc; i++) {
657 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
659 opkg_message(conf, OPKG_ERROR,
660 "Cannot find package %s.\n"
661 "Check the spelling or perhaps run 'opkg update'\n",
666 err = opkg_download_pkg(conf, pkg, ".");
669 opkg_message(conf, OPKG_ERROR,
670 "Failed to download %s\n", pkg->name);
672 opkg_message(conf, OPKG_NOTICE,
673 "Downloaded %s as %s\n",
674 pkg->name, pkg->local_filename);
682 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
685 pkg_vec_t *available;
687 char *pkg_name = NULL;
692 available = pkg_vec_alloc();
693 pkg_hash_fetch_available(&conf->pkg_hash, available);
694 pkg_vec_sort(available, pkg_compare_names);
695 for (i=0; i < available->len; i++) {
696 pkg = available->pkgs[i];
697 /* if we have package name or pattern and pkg does not match, then skip it */
698 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
702 pkg_vec_free(available);
708 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
711 pkg_vec_t *available;
713 char *pkg_name = NULL;
718 available = pkg_vec_alloc();
719 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
720 pkg_vec_sort(available, pkg_compare_names);
721 for (i=0; i < available->len; i++) {
722 pkg = available->pkgs[i];
723 /* if we have package name or pattern and pkg does not match, then skip it */
724 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
729 pkg_vec_free(available);
734 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
736 struct active_list *head = prepare_upgrade_list(conf);
737 struct active_list *node=NULL;
738 pkg_t *_old_pkg, *_new_pkg;
740 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
741 _old_pkg = list_entry(node, pkg_t, list);
742 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
743 old_v = pkg_version_str_alloc(_old_pkg);
744 new_v = pkg_version_str_alloc(_new_pkg);
745 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
749 active_list_head_delete(head);
753 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
756 pkg_vec_t *available;
758 char *pkg_name = NULL;
764 available = pkg_vec_alloc();
766 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
768 pkg_hash_fetch_available(&conf->pkg_hash, available);
770 for (i=0; i < available->len; i++) {
771 pkg = available->pkgs[i];
772 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
776 pkg_formatted_info(stdout, pkg);
778 if (conf->verbosity > 1) {
779 conffile_list_elt_t *iter;
780 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
781 conffile_t *cf = (conffile_t *)iter->data;
782 int modified = conffile_has_been_modified(conf, cf);
784 opkg_message(conf, OPKG_NOTICE,
785 "conffile=%s md5sum=%s modified=%d\n",
786 cf->name, cf->value, modified);
790 pkg_vec_free(available);
795 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
797 return opkg_info_status_cmd(conf, argc, argv, 0);
800 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
802 return opkg_info_status_cmd(conf, argc, argv, 1);
805 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
810 char *pkg_name = NULL;
814 err = opkg_configure_packages (conf, pkg_name);
817 err = opkg_configure_packages (conf, NULL);
820 write_status_files_if_changed(conf);
825 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
831 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
832 err = glob(globpattern, 0, NULL, &globbuf);
838 opkg_message(conf, OPKG_NOTICE,
839 "The following packages in %s will now be installed.\n",
841 for (i = 0; i < globbuf.gl_pathc; i++) {
842 opkg_message(conf, OPKG_NOTICE,
843 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
845 opkg_message(conf, OPKG_NOTICE, "\n");
846 for (i = 0; i < globbuf.gl_pathc; i++) {
847 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
849 err = unlink(globbuf.gl_pathv[i]);
851 opkg_message(conf, OPKG_ERROR,
852 "%s: ERROR: failed to unlink %s: %s\n",
853 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
863 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
867 pkg_t *pkg_to_remove;
868 pkg_vec_t *available;
869 char *pkg_name = NULL;
871 signal(SIGINT, sigint_handler);
873 // ENH: Add the "no pkg removed" just in case.
877 pkg_info_preinstall_check(conf);
879 available = pkg_vec_alloc();
880 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
881 for (i=0; i < argc; i++) {
882 pkg_name = calloc(1, strlen(argv[i])+2);
883 strcpy(pkg_name,argv[i]);
884 for (a=0; a < available->len; a++) {
885 pkg = available->pkgs[a];
886 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
889 if (conf->restrict_to_default_dest) {
890 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
894 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
897 if (pkg_to_remove == NULL) {
898 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
901 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
902 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
905 opkg_remove_pkg(conf, pkg_to_remove,0);
910 pkg_vec_free(available);
912 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
914 int flagged_pkg_count = 0;
917 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
919 for (i = 0; i < installed_pkgs->len; i++) {
920 pkg_t *pkg = installed_pkgs->pkgs[i];
921 if (pkg->state_flag & SF_USER) {
924 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
925 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
928 if (!flagged_pkg_count) {
929 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
930 "so refusing to uninstall unflagged non-leaf packages\n");
934 /* find packages not flagged SF_USER (i.e., installed to
935 * satisfy a dependence) and not having any dependents, and
939 for (i = 0; i < installed_pkgs->len; i++) {
940 pkg_t *pkg = installed_pkgs->pkgs[i];
941 if (!(pkg->state_flag & SF_USER)
942 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
944 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
945 opkg_remove_pkg(conf, pkg,0);
950 pkg_vec_free(installed_pkgs);
954 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
956 write_status_files_if_changed(conf);
960 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
966 signal(SIGINT, sigint_handler);
968 pkg_info_preinstall_check(conf);
970 for (i=0; i < argc; i++) {
971 if (conf->restrict_to_default_dest) {
972 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
976 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
980 opkg_message(conf, OPKG_ERROR,
981 "Package %s is not installed.\n", argv[i]);
984 opkg_purge_pkg(conf, pkg);
987 write_status_files_if_changed(conf);
991 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
995 const char *flags = argv[0];
998 signal(SIGINT, sigint_handler);
1000 for (i=1; i < argc; i++) {
1001 if (conf->restrict_to_default_dest) {
1002 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1004 conf->default_dest);
1006 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1010 opkg_message(conf, OPKG_ERROR,
1011 "Package %s is not installed.\n", argv[i]);
1014 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1015 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1016 pkg->state_flag = pkg_state_flag_from_str(flags);
1018 /* pb_ asked this feature 03292004 */
1019 /* Actually I will use only this two, but this is an open for various status */
1020 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1021 pkg->state_status = pkg_state_status_from_str(flags);
1023 opkg_state_changed++;
1024 opkg_message(conf, OPKG_NOTICE,
1025 "Setting flags for package %s to %s\n",
1029 write_status_files_if_changed(conf);
1033 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1037 str_list_elt_t *iter;
1044 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1047 opkg_message(conf, OPKG_ERROR,
1048 "Package %s not installed.\n", argv[0]);
1052 files = pkg_get_installed_files(pkg);
1053 pkg_version = pkg_version_str_alloc(pkg);
1055 printf("Package %s (%s) is installed on %s and has the following files:\n",
1056 pkg->name, pkg_version, pkg->dest->name);
1058 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
1059 printf("%s\n", (char *)iter->data);
1062 pkg_free_installed_files(pkg);
1067 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1071 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1072 const char *rel_str = "depends on";
1075 pkg_info_preinstall_check(conf);
1077 if (conf->query_all)
1078 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1080 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1081 for (i = 0; i < argc; i++) {
1082 const char *target = argv[i];
1085 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1087 for (j = 0; j < available_pkgs->len; j++) {
1088 pkg_t *pkg = available_pkgs->pkgs[j];
1089 if (fnmatch(target, pkg->name, 0) == 0) {
1091 int count = pkg->depends_count + pkg->pre_depends_count;
1092 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1093 target, pkg->architecture, rel_str);
1094 for (k = 0; k < count; k++) {
1095 compound_depend_t *cdepend = &pkg->depends[k];
1097 for (l = 0; l < cdepend->possibility_count; l++) {
1098 depend_t *possibility = cdepend->possibilities[l];
1099 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1100 if (conf->verbosity > 0) {
1101 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1102 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1103 if (possibility->version) {
1104 char *typestr = NULL;
1105 switch (possibility->constraint) {
1106 case NONE: typestr = "none"; break;
1107 case EARLIER: typestr = "<"; break;
1108 case EARLIER_EQUAL: typestr = "<="; break;
1109 case EQUAL: typestr = "="; break;
1110 case LATER_EQUAL: typestr = ">="; break;
1111 case LATER: typestr = ">"; break;
1113 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1117 opkg_message(conf, OPKG_ERROR, "\n");
1123 pkg_vec_free(available_pkgs);
1128 enum what_field_type {
1137 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1141 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1142 const char *rel_str = NULL;
1146 switch (what_field_type) {
1147 case WHATDEPENDS: rel_str = "depends on"; break;
1148 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1149 case WHATSUGGESTS: rel_str = "suggests"; break;
1150 case WHATRECOMMENDS: rel_str = "recommends"; break;
1151 case WHATPROVIDES: rel_str = "provides"; break;
1152 case WHATREPLACES: rel_str = "replaces"; break;
1155 if (conf->query_all)
1156 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1158 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1160 /* mark the root set */
1161 pkg_vec_clear_marks(available_pkgs);
1162 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1163 for (i = 0; i < argc; i++) {
1164 const char *dependee_pattern = argv[i];
1165 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1167 for (i = 0; i < available_pkgs->len; i++) {
1168 pkg_t *pkg = available_pkgs->pkgs[i];
1169 if (pkg->state_flag & SF_MARKED) {
1170 /* mark the parent (abstract) package */
1171 pkg_mark_provides(pkg);
1172 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1176 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1181 for (j = 0; j < available_pkgs->len; j++) {
1182 pkg_t *pkg = available_pkgs->pkgs[j];
1184 int count = ((what_field_type == WHATCONFLICTS)
1185 ? pkg->conflicts_count
1186 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1187 /* skip this package if it is already marked */
1188 if (pkg->parent->state_flag & SF_MARKED) {
1191 for (k = 0; k < count; k++) {
1192 compound_depend_t *cdepend =
1193 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1195 for (l = 0; l < cdepend->possibility_count; l++) {
1196 depend_t *possibility = cdepend->possibilities[l];
1197 if (possibility->pkg->state_flag & SF_MARKED) {
1198 /* mark the depending package so we won't visit it again */
1199 pkg->state_flag |= SF_MARKED;
1200 pkg_mark_provides(pkg);
1203 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1204 if (conf->verbosity > 0) {
1205 char *ver = pkg_version_str_alloc(pkg);
1206 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1207 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1208 if (possibility->version) {
1209 char *typestr = NULL;
1210 switch (possibility->constraint) {
1211 case NONE: typestr = "none"; break;
1212 case EARLIER: typestr = "<"; break;
1213 case EARLIER_EQUAL: typestr = "<="; break;
1214 case EQUAL: typestr = "="; break;
1215 case LATER_EQUAL: typestr = ">="; break;
1216 case LATER: typestr = ">"; break;
1218 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1221 if (!pkg_dependence_satisfiable(conf, possibility))
1222 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1224 opkg_message(conf, OPKG_NOTICE, "\n");
1232 } while (changed && recursive);
1233 pkg_vec_free(available_pkgs);
1239 static int pkg_mark_provides(pkg_t *pkg)
1241 int provides_count = pkg->provides_count;
1242 abstract_pkg_t **provides = pkg->provides;
1244 pkg->parent->state_flag |= SF_MARKED;
1245 for (i = 0; i < provides_count; i++) {
1246 provides[i]->state_flag |= SF_MARKED;
1251 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1253 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1255 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1257 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1260 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1262 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1265 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1267 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1270 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1272 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1275 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1279 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1280 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1283 pkg_info_preinstall_check(conf);
1285 if (conf->query_all)
1286 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1288 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1289 for (i = 0; i < argc; i++) {
1290 const char *target = argv[i];
1293 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1295 for (j = 0; j < available_pkgs->len; j++) {
1296 pkg_t *pkg = available_pkgs->pkgs[j];
1298 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1299 for (k = 0; k < count; k++) {
1300 abstract_pkg_t *apkg =
1301 ((what_field_type == WHATPROVIDES)
1303 : pkg->replaces[k]);
1304 if (fnmatch(target, apkg->name, 0) == 0) {
1305 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1306 if (strcmp(target, apkg->name) != 0)
1307 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1308 opkg_message(conf, OPKG_ERROR, "\n");
1313 pkg_vec_free(available_pkgs);
1318 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1320 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1323 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1325 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1328 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1332 pkg_vec_t *installed;
1334 str_list_t *installed_files;
1335 str_list_elt_t *iter;
1336 char *installed_file;
1342 installed = pkg_vec_alloc();
1343 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1344 pkg_vec_sort(installed, pkg_compare_names);
1346 for (i=0; i < installed->len; i++) {
1347 pkg = installed->pkgs[i];
1349 installed_files = pkg_get_installed_files(pkg);
1351 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1352 installed_file = (char *)iter->data;
1353 if (fnmatch(argv[0], installed_file, 0)==0)
1357 pkg_free_installed_files(pkg);
1360 pkg_vec_free(installed);
1365 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1368 /* this is a bit gross */
1370 parseVersion(&p1, argv[0]);
1371 parseVersion(&p2, argv[2]);
1372 return pkg_version_satisfied(&p1, &p2, argv[1]);
1374 opkg_message(conf, OPKG_ERROR,
1375 "opkg compare_versions <v1> <op> <v2>\n"
1376 "<op> is one of <= >= << >> =\n");
1381 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1383 nv_pair_list_elt_t *l;
1385 list_for_each_entry(l, &conf->arch_list.head, node) {
1386 nv_pair_t *nv = (nv_pair_t *)l->data;
1387 printf("arch %s %s\n", nv->name, nv->value);