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);
343 dir = opendir (ctx->statedir);
346 while (de = readdir (dir), de != NULL) {
349 if (de->d_name[0] == '.')
352 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
353 if (access (path, X_OK) == 0) {
363 perror (ctx->statedir);
365 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
369 free (ctx->statedir);
375 /* For package pkg do the following: If it is already visited, return. If not,
376 add it in visited list and recurse to its deps. Finally, add it to ordered
378 pkg_vec all contains all available packages in repos.
379 pkg_vec visited contains packages already visited by this function, and is
380 used to end recursion and avoid an infinite loop on graph cycles.
381 pkg_vec ordered will finally contain the ordered set of packages.
383 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
384 pkg_vec_t *visited, pkg_vec_t *ordered)
389 compound_depend_t * compound_depend;
390 depend_t ** possible_satisfiers;
391 abstract_pkg_t *abpkg;
392 abstract_pkg_t **dependents;
394 /* If it's just an available package, that is, not installed and not even
396 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
397 would do here. However, if there is an intermediate node (pkg) that is
398 configured and installed between two unpacked packages, the latter
399 won't be properly reordered, unless all installed/unpacked pkgs are
401 if (pkg->state_status == SS_NOT_INSTALLED)
404 /* If the package has already been visited (by this function), skip it */
405 for(j = 0; j < visited->len; j++)
406 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
407 opkg_message(conf, OPKG_INFO,
408 " pkg: %s already visited\n", pkg->name);
412 pkg_vec_insert(visited, pkg);
414 count = pkg->pre_depends_count + pkg->depends_count + \
415 pkg->recommends_count + pkg->suggests_count;
417 opkg_message(conf, OPKG_INFO,
418 " pkg: %s\n", pkg->name);
420 /* Iterate over all the dependencies of pkg. For each one, find a package
421 that is either installed or unpacked and satisfies this dependency.
422 (there should only be one such package per dependency installed or
423 unpacked). Then recurse to the dependency package */
424 for (j=0; j < count ; j++) {
425 compound_depend = &pkg->depends[j];
426 possible_satisfiers = compound_depend->possibilities;
427 for (k=0; k < compound_depend->possibility_count ; k++) {
428 abpkg = possible_satisfiers[k]->pkg;
429 dependents = abpkg->provided_by->pkgs;
431 if (dependents != NULL)
432 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
433 opkg_message(conf, OPKG_INFO,
434 " Descending on pkg: %s\n",
435 dependents [l]->name);
437 /* find whether dependent l is installed or unpacked,
438 * and then find which package in the list satisfies it */
439 for(m = 0; m < all->len; m++) {
441 if ( dep->state_status != SS_NOT_INSTALLED)
442 if ( ! strcmp(dep->name, dependents[l]->name)) {
443 opkg_recurse_pkgs_in_order(conf, dep, all,
445 /* Stop the outer loop */
446 l = abpkg->provided_by->len;
447 /* break from the inner loop */
456 /* When all recursions from this node down, are over, and all
457 dependencies have been added in proper order in the ordered array, add
458 also the package pkg to ordered array */
459 pkg_vec_insert(ordered, pkg);
465 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
467 pkg_vec_t *all, *ordered, *visited;
473 opkg_message(conf, OPKG_INFO,
474 "Configuring unpacked packages\n");
477 all = pkg_vec_alloc();
479 pkg_hash_fetch_available(&conf->pkg_hash, all);
481 /* Reorder pkgs in order to be configured according to the Depends: tag
483 opkg_message(conf, OPKG_INFO,
484 "Reordering packages before configuring them...\n");
485 ordered = pkg_vec_alloc();
486 visited = pkg_vec_alloc();
487 for(i = 0; i < all->len; i++) {
489 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
493 ic = opkg_prep_intercepts (conf);
495 for(i = 0; i < all->len; i++) {
498 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
501 if (pkg->state_status == SS_UNPACKED) {
502 opkg_message(conf, OPKG_NOTICE,
503 "Configuring %s\n", pkg->name);
505 r = opkg_configure(conf, pkg);
507 pkg->state_status = SS_INSTALLED;
508 pkg->parent->state_status = SS_INSTALLED;
509 pkg->state_flag &= ~SF_PREFER;
517 r = opkg_finalize_intercepts (ic);
522 pkg_vec_free(ordered);
523 pkg_vec_free(visited);
528 static opkg_conf_t *global_conf;
530 static void sigint_handler(int sig)
532 signal(sig, SIG_DFL);
533 opkg_message(NULL, OPKG_NOTICE,
534 "opkg: interrupted. writing out status database\n");
535 write_status_files_if_changed(global_conf);
539 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
546 signal(SIGINT, sigint_handler);
549 * Now scan through package names and install
551 for (i=0; i < argc; i++) {
554 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
555 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
556 if (err != EINVAL && err != 0)
559 pkg_info_preinstall_check(conf);
561 for (i=0; i < argc; i++) {
563 err = opkg_install_by_name(conf, arg);
564 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
565 opkg_message(conf, OPKG_ERROR,
566 "Cannot find package %s.\n",
571 /* recheck to verify that all dependences are satisfied */
572 if (0) opkg_satisfy_all_dependences(conf);
574 opkg_configure_packages(conf, NULL);
576 write_status_files_if_changed(conf);
581 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
588 signal(SIGINT, sigint_handler);
591 for (i=0; i < argc; i++) {
594 err = opkg_prepare_url_for_install(conf, arg, &arg);
595 if (err != EINVAL && err != 0)
598 pkg_info_preinstall_check(conf);
600 for (i=0; i < argc; i++) {
602 if (conf->restrict_to_default_dest) {
603 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
607 opkg_message(conf, OPKG_NOTICE,
608 "Package %s not installed in %s\n",
609 argv[i], conf->default_dest->name);
613 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
617 opkg_upgrade_pkg(conf, pkg);
619 opkg_install_by_name(conf, arg);
623 pkg_vec_t *installed = pkg_vec_alloc();
625 pkg_info_preinstall_check(conf);
627 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
628 for (i = 0; i < installed->len; i++) {
629 pkg = installed->pkgs[i];
630 opkg_upgrade_pkg(conf, pkg);
632 pkg_vec_free(installed);
635 /* recheck to verify that all dependences are satisfied */
636 if (0) opkg_satisfy_all_dependences(conf);
638 opkg_configure_packages(conf, NULL);
640 write_status_files_if_changed(conf);
645 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
651 pkg_info_preinstall_check(conf);
652 for (i = 0; i < argc; i++) {
655 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
657 opkg_message(conf, OPKG_ERROR,
658 "Cannot find package %s.\n"
659 "Check the spelling or perhaps run 'opkg update'\n",
664 err = opkg_download_pkg(conf, pkg, ".");
667 opkg_message(conf, OPKG_ERROR,
668 "Failed to download %s\n", pkg->name);
670 opkg_message(conf, OPKG_NOTICE,
671 "Downloaded %s as %s\n",
672 pkg->name, pkg->local_filename);
680 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
683 pkg_vec_t *available;
685 char *pkg_name = NULL;
690 available = pkg_vec_alloc();
691 pkg_hash_fetch_available(&conf->pkg_hash, available);
692 pkg_vec_sort(available, pkg_compare_names);
693 for (i=0; i < available->len; i++) {
694 pkg = available->pkgs[i];
695 /* if we have package name or pattern and pkg does not match, then skip it */
696 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
700 pkg_vec_free(available);
706 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
709 pkg_vec_t *available;
711 char *pkg_name = NULL;
716 available = pkg_vec_alloc();
717 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
718 pkg_vec_sort(available, pkg_compare_names);
719 for (i=0; i < available->len; i++) {
720 pkg = available->pkgs[i];
721 /* if we have package name or pattern and pkg does not match, then skip it */
722 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
727 pkg_vec_free(available);
732 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
734 struct active_list *head = prepare_upgrade_list(conf);
735 struct active_list *node=NULL;
736 pkg_t *_old_pkg, *_new_pkg;
738 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
739 _old_pkg = list_entry(node, pkg_t, list);
740 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
741 old_v = pkg_version_str_alloc(_old_pkg);
742 new_v = pkg_version_str_alloc(_new_pkg);
743 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
747 active_list_head_delete(head);
751 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
754 pkg_vec_t *available;
756 char *pkg_name = NULL;
762 available = pkg_vec_alloc();
764 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
766 pkg_hash_fetch_available(&conf->pkg_hash, available);
768 for (i=0; i < available->len; i++) {
769 pkg = available->pkgs[i];
770 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
774 pkg_formatted_info(stdout, pkg);
776 if (conf->verbosity > 1) {
777 conffile_list_elt_t *iter;
778 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
779 conffile_t *cf = (conffile_t *)iter->data;
780 int modified = conffile_has_been_modified(conf, cf);
782 opkg_message(conf, OPKG_NOTICE,
783 "conffile=%s md5sum=%s modified=%d\n",
784 cf->name, cf->value, modified);
788 pkg_vec_free(available);
793 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
795 return opkg_info_status_cmd(conf, argc, argv, 0);
798 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
800 return opkg_info_status_cmd(conf, argc, argv, 1);
803 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
808 char *pkg_name = NULL;
812 err = opkg_configure_packages (conf, pkg_name);
815 err = opkg_configure_packages (conf, NULL);
818 write_status_files_if_changed(conf);
823 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
829 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
830 err = glob(globpattern, 0, NULL, &globbuf);
836 opkg_message(conf, OPKG_NOTICE,
837 "The following packages in %s will now be installed.\n",
839 for (i = 0; i < globbuf.gl_pathc; i++) {
840 opkg_message(conf, OPKG_NOTICE,
841 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
843 opkg_message(conf, OPKG_NOTICE, "\n");
844 for (i = 0; i < globbuf.gl_pathc; i++) {
845 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
847 err = unlink(globbuf.gl_pathv[i]);
849 opkg_message(conf, OPKG_ERROR,
850 "%s: ERROR: failed to unlink %s: %s\n",
851 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
861 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
865 pkg_t *pkg_to_remove;
866 pkg_vec_t *available;
867 char *pkg_name = NULL;
869 signal(SIGINT, sigint_handler);
871 // ENH: Add the "no pkg removed" just in case.
875 pkg_info_preinstall_check(conf);
877 available = pkg_vec_alloc();
878 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
879 for (i=0; i < argc; i++) {
880 pkg_name = calloc(1, strlen(argv[i])+2);
881 strcpy(pkg_name,argv[i]);
882 for (a=0; a < available->len; a++) {
883 pkg = available->pkgs[a];
884 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
887 if (conf->restrict_to_default_dest) {
888 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
892 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
895 if (pkg_to_remove == NULL) {
896 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
899 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
900 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
903 opkg_remove_pkg(conf, pkg_to_remove,0);
908 pkg_vec_free(available);
910 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
912 int flagged_pkg_count = 0;
915 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
917 for (i = 0; i < installed_pkgs->len; i++) {
918 pkg_t *pkg = installed_pkgs->pkgs[i];
919 if (pkg->state_flag & SF_USER) {
922 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
923 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
926 if (!flagged_pkg_count) {
927 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
928 "so refusing to uninstall unflagged non-leaf packages\n");
932 /* find packages not flagged SF_USER (i.e., installed to
933 * satisfy a dependence) and not having any dependents, and
937 for (i = 0; i < installed_pkgs->len; i++) {
938 pkg_t *pkg = installed_pkgs->pkgs[i];
939 if (!(pkg->state_flag & SF_USER)
940 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
942 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
943 opkg_remove_pkg(conf, pkg,0);
948 pkg_vec_free(installed_pkgs);
952 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
954 write_status_files_if_changed(conf);
958 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
964 signal(SIGINT, sigint_handler);
966 pkg_info_preinstall_check(conf);
968 for (i=0; i < argc; i++) {
969 if (conf->restrict_to_default_dest) {
970 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
974 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
978 opkg_message(conf, OPKG_ERROR,
979 "Package %s is not installed.\n", argv[i]);
982 opkg_purge_pkg(conf, pkg);
985 write_status_files_if_changed(conf);
989 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
993 const char *flags = argv[0];
996 signal(SIGINT, sigint_handler);
998 for (i=1; i < argc; i++) {
999 if (conf->restrict_to_default_dest) {
1000 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1002 conf->default_dest);
1004 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1008 opkg_message(conf, OPKG_ERROR,
1009 "Package %s is not installed.\n", argv[i]);
1012 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1013 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1014 pkg->state_flag = pkg_state_flag_from_str(flags);
1016 /* pb_ asked this feature 03292004 */
1017 /* Actually I will use only this two, but this is an open for various status */
1018 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1019 pkg->state_status = pkg_state_status_from_str(flags);
1021 opkg_state_changed++;
1022 opkg_message(conf, OPKG_NOTICE,
1023 "Setting flags for package %s to %s\n",
1027 write_status_files_if_changed(conf);
1031 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1035 str_list_elt_t *iter;
1042 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1045 opkg_message(conf, OPKG_ERROR,
1046 "Package %s not installed.\n", argv[0]);
1050 files = pkg_get_installed_files(pkg);
1051 pkg_version = pkg_version_str_alloc(pkg);
1053 printf("Package %s (%s) is installed on %s and has the following files:\n",
1054 pkg->name, pkg_version, pkg->dest->name);
1056 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
1057 printf("%s\n", (char *)iter->data);
1060 pkg_free_installed_files(pkg);
1065 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1069 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1070 const char *rel_str = "depends on";
1073 pkg_info_preinstall_check(conf);
1075 if (conf->query_all)
1076 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1078 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1079 for (i = 0; i < argc; i++) {
1080 const char *target = argv[i];
1083 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1085 for (j = 0; j < available_pkgs->len; j++) {
1086 pkg_t *pkg = available_pkgs->pkgs[j];
1087 if (fnmatch(target, pkg->name, 0) == 0) {
1089 int count = pkg->depends_count + pkg->pre_depends_count;
1090 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1091 target, pkg->architecture, rel_str);
1092 for (k = 0; k < count; k++) {
1093 compound_depend_t *cdepend = &pkg->depends[k];
1095 for (l = 0; l < cdepend->possibility_count; l++) {
1096 depend_t *possibility = cdepend->possibilities[l];
1097 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1098 if (conf->verbosity > 0) {
1099 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1100 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1101 if (possibility->version) {
1102 char *typestr = NULL;
1103 switch (possibility->constraint) {
1104 case NONE: typestr = "none"; break;
1105 case EARLIER: typestr = "<"; break;
1106 case EARLIER_EQUAL: typestr = "<="; break;
1107 case EQUAL: typestr = "="; break;
1108 case LATER_EQUAL: typestr = ">="; break;
1109 case LATER: typestr = ">"; break;
1111 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1115 opkg_message(conf, OPKG_ERROR, "\n");
1121 pkg_vec_free(available_pkgs);
1126 enum what_field_type {
1135 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1139 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1140 const char *rel_str = NULL;
1144 switch (what_field_type) {
1145 case WHATDEPENDS: rel_str = "depends on"; break;
1146 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1147 case WHATSUGGESTS: rel_str = "suggests"; break;
1148 case WHATRECOMMENDS: rel_str = "recommends"; break;
1149 case WHATPROVIDES: rel_str = "provides"; break;
1150 case WHATREPLACES: rel_str = "replaces"; break;
1153 if (conf->query_all)
1154 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1156 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1158 /* mark the root set */
1159 pkg_vec_clear_marks(available_pkgs);
1160 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1161 for (i = 0; i < argc; i++) {
1162 const char *dependee_pattern = argv[i];
1163 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1165 for (i = 0; i < available_pkgs->len; i++) {
1166 pkg_t *pkg = available_pkgs->pkgs[i];
1167 if (pkg->state_flag & SF_MARKED) {
1168 /* mark the parent (abstract) package */
1169 pkg_mark_provides(pkg);
1170 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1174 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1179 for (j = 0; j < available_pkgs->len; j++) {
1180 pkg_t *pkg = available_pkgs->pkgs[j];
1182 int count = ((what_field_type == WHATCONFLICTS)
1183 ? pkg->conflicts_count
1184 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1185 /* skip this package if it is already marked */
1186 if (pkg->parent->state_flag & SF_MARKED) {
1189 for (k = 0; k < count; k++) {
1190 compound_depend_t *cdepend =
1191 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1193 for (l = 0; l < cdepend->possibility_count; l++) {
1194 depend_t *possibility = cdepend->possibilities[l];
1195 if (possibility->pkg->state_flag & SF_MARKED) {
1196 /* mark the depending package so we won't visit it again */
1197 pkg->state_flag |= SF_MARKED;
1198 pkg_mark_provides(pkg);
1201 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1202 if (conf->verbosity > 0) {
1203 char *ver = pkg_version_str_alloc(pkg);
1204 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1205 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1206 if (possibility->version) {
1207 char *typestr = NULL;
1208 switch (possibility->constraint) {
1209 case NONE: typestr = "none"; break;
1210 case EARLIER: typestr = "<"; break;
1211 case EARLIER_EQUAL: typestr = "<="; break;
1212 case EQUAL: typestr = "="; break;
1213 case LATER_EQUAL: typestr = ">="; break;
1214 case LATER: typestr = ">"; break;
1216 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1219 if (!pkg_dependence_satisfiable(conf, possibility))
1220 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1222 opkg_message(conf, OPKG_NOTICE, "\n");
1230 } while (changed && recursive);
1231 pkg_vec_free(available_pkgs);
1237 static int pkg_mark_provides(pkg_t *pkg)
1239 int provides_count = pkg->provides_count;
1240 abstract_pkg_t **provides = pkg->provides;
1242 pkg->parent->state_flag |= SF_MARKED;
1243 for (i = 0; i < provides_count; i++) {
1244 provides[i]->state_flag |= SF_MARKED;
1249 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1251 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1253 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1255 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1258 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1260 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1263 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1265 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1268 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1270 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1273 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1277 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1278 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1281 pkg_info_preinstall_check(conf);
1283 if (conf->query_all)
1284 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1286 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1287 for (i = 0; i < argc; i++) {
1288 const char *target = argv[i];
1291 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1293 for (j = 0; j < available_pkgs->len; j++) {
1294 pkg_t *pkg = available_pkgs->pkgs[j];
1296 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1297 for (k = 0; k < count; k++) {
1298 abstract_pkg_t *apkg =
1299 ((what_field_type == WHATPROVIDES)
1301 : pkg->replaces[k]);
1302 if (fnmatch(target, apkg->name, 0) == 0) {
1303 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1304 if (strcmp(target, apkg->name) != 0)
1305 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1306 opkg_message(conf, OPKG_ERROR, "\n");
1311 pkg_vec_free(available_pkgs);
1316 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1318 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1321 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1323 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1326 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1330 pkg_vec_t *installed;
1332 str_list_t *installed_files;
1333 str_list_elt_t *iter;
1334 char *installed_file;
1340 installed = pkg_vec_alloc();
1341 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1342 pkg_vec_sort(installed, pkg_compare_names);
1344 for (i=0; i < installed->len; i++) {
1345 pkg = installed->pkgs[i];
1347 installed_files = pkg_get_installed_files(pkg);
1349 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1350 installed_file = (char *)iter->data;
1351 if (fnmatch(argv[0], installed_file, 0)==0)
1355 pkg_free_installed_files(pkg);
1358 pkg_vec_free(installed);
1363 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1366 /* this is a bit gross */
1368 parseVersion(&p1, argv[0]);
1369 parseVersion(&p2, argv[2]);
1370 return pkg_version_satisfied(&p1, &p2, argv[1]);
1372 opkg_message(conf, OPKG_ERROR,
1373 "opkg compare_versions <v1> <op> <v2>\n"
1374 "<op> is one of <= >= << >> =\n");
1379 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1381 nv_pair_list_elt_t *l;
1383 list_for_each_entry(l, &conf->arch_list.head, node) {
1384 nv_pair_t *nv = (nv_pair_t *)l->data;
1385 printf("arch %s %s\n", nv->name, nv->value);