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);
791 opkg_message(conf, OPKG_NOTICE,
792 "conffile=%s md5sum=%s modified=%d\n",
793 cf->name, cf->value, modified);
797 pkg_vec_free(available);
802 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
804 return opkg_info_status_cmd(conf, argc, argv, 0);
807 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
809 return opkg_info_status_cmd(conf, argc, argv, 1);
812 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
817 char *pkg_name = NULL;
821 err = opkg_configure_packages (conf, pkg_name);
824 err = opkg_configure_packages (conf, NULL);
827 write_status_files_if_changed(conf);
832 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
838 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
839 err = glob(globpattern, 0, NULL, &globbuf);
845 opkg_message(conf, OPKG_NOTICE,
846 "The following packages in %s will now be installed.\n",
848 for (i = 0; i < globbuf.gl_pathc; i++) {
849 opkg_message(conf, OPKG_NOTICE,
850 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
852 opkg_message(conf, OPKG_NOTICE, "\n");
853 for (i = 0; i < globbuf.gl_pathc; i++) {
854 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
856 err = unlink(globbuf.gl_pathv[i]);
858 opkg_message(conf, OPKG_ERROR,
859 "%s: ERROR: failed to unlink %s: %s\n",
860 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
870 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
874 pkg_t *pkg_to_remove;
875 pkg_vec_t *available;
876 char *pkg_name = NULL;
878 signal(SIGINT, sigint_handler);
880 // ENH: Add the "no pkg removed" just in case.
884 pkg_info_preinstall_check(conf);
886 available = pkg_vec_alloc();
887 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
888 for (i=0; i < argc; i++) {
889 pkg_name = calloc(1, strlen(argv[i])+2);
890 strcpy(pkg_name,argv[i]);
891 for (a=0; a < available->len; a++) {
892 pkg = available->pkgs[a];
893 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
896 if (conf->restrict_to_default_dest) {
897 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
901 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
904 if (pkg_to_remove == NULL) {
905 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
908 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
909 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
912 opkg_remove_pkg(conf, pkg_to_remove,0);
917 pkg_vec_free(available);
919 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
921 int flagged_pkg_count = 0;
924 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
926 for (i = 0; i < installed_pkgs->len; i++) {
927 pkg_t *pkg = installed_pkgs->pkgs[i];
928 if (pkg->state_flag & SF_USER) {
931 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
932 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
935 if (!flagged_pkg_count) {
936 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
937 "so refusing to uninstall unflagged non-leaf packages\n");
941 /* find packages not flagged SF_USER (i.e., installed to
942 * satisfy a dependence) and not having any dependents, and
946 for (i = 0; i < installed_pkgs->len; i++) {
947 pkg_t *pkg = installed_pkgs->pkgs[i];
948 if (!(pkg->state_flag & SF_USER)
949 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
951 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
952 opkg_remove_pkg(conf, pkg,0);
957 pkg_vec_free(installed_pkgs);
961 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
963 write_status_files_if_changed(conf);
967 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
973 signal(SIGINT, sigint_handler);
975 pkg_info_preinstall_check(conf);
977 for (i=0; i < argc; i++) {
978 if (conf->restrict_to_default_dest) {
979 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
983 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
987 opkg_message(conf, OPKG_ERROR,
988 "Package %s is not installed.\n", argv[i]);
991 opkg_purge_pkg(conf, pkg);
994 write_status_files_if_changed(conf);
998 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1002 const char *flags = argv[0];
1005 signal(SIGINT, sigint_handler);
1007 for (i=1; i < argc; i++) {
1008 if (conf->restrict_to_default_dest) {
1009 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1011 conf->default_dest);
1013 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1017 opkg_message(conf, OPKG_ERROR,
1018 "Package %s is not installed.\n", argv[i]);
1021 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1022 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1023 pkg->state_flag = pkg_state_flag_from_str(flags);
1025 /* pb_ asked this feature 03292004 */
1026 /* Actually I will use only this two, but this is an open for various status */
1027 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1028 pkg->state_status = pkg_state_status_from_str(flags);
1030 opkg_state_changed++;
1031 opkg_message(conf, OPKG_NOTICE,
1032 "Setting flags for package %s to %s\n",
1036 write_status_files_if_changed(conf);
1040 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1044 str_list_elt_t *iter;
1051 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1054 opkg_message(conf, OPKG_ERROR,
1055 "Package %s not installed.\n", argv[0]);
1059 files = pkg_get_installed_files(pkg);
1060 pkg_version = pkg_version_str_alloc(pkg);
1062 printf("Package %s (%s) is installed on %s and has the following files:\n",
1063 pkg->name, pkg_version, pkg->dest->name);
1065 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
1066 printf("%s\n", (char *)iter->data);
1069 pkg_free_installed_files(pkg);
1074 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1078 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1079 const char *rel_str = "depends on";
1082 pkg_info_preinstall_check(conf);
1084 if (conf->query_all)
1085 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1087 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1088 for (i = 0; i < argc; i++) {
1089 const char *target = argv[i];
1092 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1094 for (j = 0; j < available_pkgs->len; j++) {
1095 pkg_t *pkg = available_pkgs->pkgs[j];
1096 if (fnmatch(target, pkg->name, 0) == 0) {
1098 int count = pkg->depends_count + pkg->pre_depends_count;
1099 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1100 target, pkg->architecture, rel_str);
1101 for (k = 0; k < count; k++) {
1102 compound_depend_t *cdepend = &pkg->depends[k];
1104 for (l = 0; l < cdepend->possibility_count; l++) {
1105 depend_t *possibility = cdepend->possibilities[l];
1106 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1107 if (conf->verbosity > 0) {
1108 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1109 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1110 if (possibility->version) {
1111 char *typestr = NULL;
1112 switch (possibility->constraint) {
1113 case NONE: typestr = "none"; break;
1114 case EARLIER: typestr = "<"; break;
1115 case EARLIER_EQUAL: typestr = "<="; break;
1116 case EQUAL: typestr = "="; break;
1117 case LATER_EQUAL: typestr = ">="; break;
1118 case LATER: typestr = ">"; break;
1120 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1124 opkg_message(conf, OPKG_ERROR, "\n");
1130 pkg_vec_free(available_pkgs);
1135 enum what_field_type {
1144 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1148 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1149 const char *rel_str = NULL;
1153 switch (what_field_type) {
1154 case WHATDEPENDS: rel_str = "depends on"; break;
1155 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1156 case WHATSUGGESTS: rel_str = "suggests"; break;
1157 case WHATRECOMMENDS: rel_str = "recommends"; break;
1158 case WHATPROVIDES: rel_str = "provides"; break;
1159 case WHATREPLACES: rel_str = "replaces"; break;
1162 if (conf->query_all)
1163 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1165 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1167 /* mark the root set */
1168 pkg_vec_clear_marks(available_pkgs);
1169 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1170 for (i = 0; i < argc; i++) {
1171 const char *dependee_pattern = argv[i];
1172 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1174 for (i = 0; i < available_pkgs->len; i++) {
1175 pkg_t *pkg = available_pkgs->pkgs[i];
1176 if (pkg->state_flag & SF_MARKED) {
1177 /* mark the parent (abstract) package */
1178 pkg_mark_provides(pkg);
1179 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1183 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1188 for (j = 0; j < available_pkgs->len; j++) {
1189 pkg_t *pkg = available_pkgs->pkgs[j];
1191 int count = ((what_field_type == WHATCONFLICTS)
1192 ? pkg->conflicts_count
1193 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1194 /* skip this package if it is already marked */
1195 if (pkg->parent->state_flag & SF_MARKED) {
1198 for (k = 0; k < count; k++) {
1199 compound_depend_t *cdepend =
1200 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1202 for (l = 0; l < cdepend->possibility_count; l++) {
1203 depend_t *possibility = cdepend->possibilities[l];
1204 if (possibility->pkg->state_flag & SF_MARKED) {
1205 /* mark the depending package so we won't visit it again */
1206 pkg->state_flag |= SF_MARKED;
1207 pkg_mark_provides(pkg);
1210 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1211 if (conf->verbosity > 0) {
1212 char *ver = pkg_version_str_alloc(pkg);
1213 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1214 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1215 if (possibility->version) {
1216 char *typestr = NULL;
1217 switch (possibility->constraint) {
1218 case NONE: typestr = "none"; break;
1219 case EARLIER: typestr = "<"; break;
1220 case EARLIER_EQUAL: typestr = "<="; break;
1221 case EQUAL: typestr = "="; break;
1222 case LATER_EQUAL: typestr = ">="; break;
1223 case LATER: typestr = ">"; break;
1225 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1228 if (!pkg_dependence_satisfiable(conf, possibility))
1229 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1231 opkg_message(conf, OPKG_NOTICE, "\n");
1239 } while (changed && recursive);
1240 pkg_vec_free(available_pkgs);
1246 static int pkg_mark_provides(pkg_t *pkg)
1248 int provides_count = pkg->provides_count;
1249 abstract_pkg_t **provides = pkg->provides;
1251 pkg->parent->state_flag |= SF_MARKED;
1252 for (i = 0; i < provides_count; i++) {
1253 provides[i]->state_flag |= SF_MARKED;
1258 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1260 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1262 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1264 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1267 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1269 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1272 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1274 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1277 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1279 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1282 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1286 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1287 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1290 pkg_info_preinstall_check(conf);
1292 if (conf->query_all)
1293 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1295 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1296 for (i = 0; i < argc; i++) {
1297 const char *target = argv[i];
1300 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1302 for (j = 0; j < available_pkgs->len; j++) {
1303 pkg_t *pkg = available_pkgs->pkgs[j];
1305 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1306 for (k = 0; k < count; k++) {
1307 abstract_pkg_t *apkg =
1308 ((what_field_type == WHATPROVIDES)
1310 : pkg->replaces[k]);
1311 if (fnmatch(target, apkg->name, 0) == 0) {
1312 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1313 if (strcmp(target, apkg->name) != 0)
1314 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1315 opkg_message(conf, OPKG_ERROR, "\n");
1320 pkg_vec_free(available_pkgs);
1325 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1327 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1330 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1332 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1335 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1339 pkg_vec_t *installed;
1341 str_list_t *installed_files;
1342 str_list_elt_t *iter;
1343 char *installed_file;
1349 installed = pkg_vec_alloc();
1350 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1351 pkg_vec_sort(installed, pkg_compare_names);
1353 for (i=0; i < installed->len; i++) {
1354 pkg = installed->pkgs[i];
1356 installed_files = pkg_get_installed_files(pkg);
1358 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1359 installed_file = (char *)iter->data;
1360 if (fnmatch(argv[0], installed_file, 0)==0)
1364 pkg_free_installed_files(pkg);
1367 pkg_vec_free(installed);
1372 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1375 /* this is a bit gross */
1377 parseVersion(&p1, argv[0]);
1378 parseVersion(&p2, argv[2]);
1379 return pkg_version_satisfied(&p1, &p2, argv[1]);
1381 opkg_message(conf, OPKG_ERROR,
1382 "opkg compare_versions <v1> <op> <v2>\n"
1383 "<op> is one of <= >= << >> =\n");
1388 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1390 nv_pair_list_elt_t *l;
1392 list_for_each_entry(l, &conf->arch_list.head, node) {
1393 nv_pair_t *nv = (nv_pair_t *)l->data;
1394 printf("arch %s %s\n", nv->name, nv->value);