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;
308 ctx = xcalloc(1, sizeof (*ctx));
309 ctx->oldpath = xstrdup(getenv("PATH"));
310 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
311 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX", conf->tmp_dir);
313 if (mkdtemp(ctx->statedir) == NULL) {
314 fprintf(stderr, "%s: mkdtemp: %s\n", __FUNCTION__, strerror(errno));
322 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
323 setenv("PATH", newpath, 1);
329 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
335 setenv ("PATH", ctx->oldpath, 1);
338 dir = opendir (ctx->statedir);
341 while (de = readdir (dir), de != NULL) {
344 if (de->d_name[0] == '.')
347 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
348 if (access (path, X_OK) == 0) {
358 perror (ctx->statedir);
360 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
364 free (ctx->statedir);
370 /* For package pkg do the following: If it is already visited, return. If not,
371 add it in visited list and recurse to its deps. Finally, add it to ordered
373 pkg_vec all contains all available packages in repos.
374 pkg_vec visited contains packages already visited by this function, and is
375 used to end recursion and avoid an infinite loop on graph cycles.
376 pkg_vec ordered will finally contain the ordered set of packages.
378 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
379 pkg_vec_t *visited, pkg_vec_t *ordered)
384 compound_depend_t * compound_depend;
385 depend_t ** possible_satisfiers;
386 abstract_pkg_t *abpkg;
387 abstract_pkg_t **dependents;
389 /* If it's just an available package, that is, not installed and not even
391 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
392 would do here. However, if there is an intermediate node (pkg) that is
393 configured and installed between two unpacked packages, the latter
394 won't be properly reordered, unless all installed/unpacked pkgs are
396 if (pkg->state_status == SS_NOT_INSTALLED)
399 /* If the package has already been visited (by this function), skip it */
400 for(j = 0; j < visited->len; j++)
401 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
402 opkg_message(conf, OPKG_INFO,
403 " pkg: %s already visited\n", pkg->name);
407 pkg_vec_insert(visited, pkg);
409 count = pkg->pre_depends_count + pkg->depends_count + \
410 pkg->recommends_count + pkg->suggests_count;
412 opkg_message(conf, OPKG_INFO,
413 " pkg: %s\n", pkg->name);
415 /* Iterate over all the dependencies of pkg. For each one, find a package
416 that is either installed or unpacked and satisfies this dependency.
417 (there should only be one such package per dependency installed or
418 unpacked). Then recurse to the dependency package */
419 for (j=0; j < count ; j++) {
420 compound_depend = &pkg->depends[j];
421 possible_satisfiers = compound_depend->possibilities;
422 for (k=0; k < compound_depend->possibility_count ; k++) {
423 abpkg = possible_satisfiers[k]->pkg;
424 dependents = abpkg->provided_by->pkgs;
426 if (dependents != NULL)
427 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
428 opkg_message(conf, OPKG_INFO,
429 " Descending on pkg: %s\n",
430 dependents [l]->name);
432 /* find whether dependent l is installed or unpacked,
433 * and then find which package in the list satisfies it */
434 for(m = 0; m < all->len; m++) {
436 if ( dep->state_status != SS_NOT_INSTALLED)
437 if ( ! strcmp(dep->name, dependents[l]->name)) {
438 opkg_recurse_pkgs_in_order(conf, dep, all,
440 /* Stop the outer loop */
441 l = abpkg->provided_by->len;
442 /* break from the inner loop */
451 /* When all recursions from this node down, are over, and all
452 dependencies have been added in proper order in the ordered array, add
453 also the package pkg to ordered array */
454 pkg_vec_insert(ordered, pkg);
460 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
462 pkg_vec_t *all, *ordered, *visited;
468 opkg_message(conf, OPKG_INFO,
469 "Configuring unpacked packages\n");
472 all = pkg_vec_alloc();
474 pkg_hash_fetch_available(&conf->pkg_hash, all);
476 /* Reorder pkgs in order to be configured according to the Depends: tag
478 opkg_message(conf, OPKG_INFO,
479 "Reordering packages before configuring them...\n");
480 ordered = pkg_vec_alloc();
481 visited = pkg_vec_alloc();
482 for(i = 0; i < all->len; i++) {
484 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
487 ic = opkg_prep_intercepts (conf);
491 for(i = 0; i < all->len; i++) {
494 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
497 if (pkg->state_status == SS_UNPACKED) {
498 opkg_message(conf, OPKG_NOTICE,
499 "Configuring %s\n", pkg->name);
501 r = opkg_configure(conf, pkg);
503 pkg->state_status = SS_INSTALLED;
504 pkg->parent->state_status = SS_INSTALLED;
505 pkg->state_flag &= ~SF_PREFER;
513 r = opkg_finalize_intercepts (ic);
518 pkg_vec_free(ordered);
519 pkg_vec_free(visited);
524 static opkg_conf_t *global_conf;
526 static void sigint_handler(int sig)
528 signal(sig, SIG_DFL);
529 opkg_message(NULL, OPKG_NOTICE,
530 "opkg: interrupted. writing out status database\n");
531 write_status_files_if_changed(global_conf);
535 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
542 signal(SIGINT, sigint_handler);
545 * Now scan through package names and install
547 for (i=0; i < argc; i++) {
550 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
551 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
552 if (err != EINVAL && err != 0)
555 pkg_info_preinstall_check(conf);
557 for (i=0; i < argc; i++) {
559 err = opkg_install_by_name(conf, arg);
560 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
561 opkg_message(conf, OPKG_ERROR,
562 "Cannot find package %s.\n",
567 opkg_configure_packages(conf, NULL);
569 write_status_files_if_changed(conf);
574 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
581 signal(SIGINT, sigint_handler);
584 for (i=0; i < argc; i++) {
587 err = opkg_prepare_url_for_install(conf, arg, &arg);
588 if (err != EINVAL && err != 0)
591 pkg_info_preinstall_check(conf);
593 for (i=0; i < argc; i++) {
595 if (conf->restrict_to_default_dest) {
596 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
600 opkg_message(conf, OPKG_NOTICE,
601 "Package %s not installed in %s\n",
602 argv[i], conf->default_dest->name);
606 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
610 opkg_upgrade_pkg(conf, pkg);
612 opkg_install_by_name(conf, arg);
616 pkg_vec_t *installed = pkg_vec_alloc();
618 pkg_info_preinstall_check(conf);
620 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
621 for (i = 0; i < installed->len; i++) {
622 pkg = installed->pkgs[i];
623 opkg_upgrade_pkg(conf, pkg);
625 pkg_vec_free(installed);
628 opkg_configure_packages(conf, NULL);
630 write_status_files_if_changed(conf);
635 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
641 pkg_info_preinstall_check(conf);
642 for (i = 0; i < argc; i++) {
645 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
647 opkg_message(conf, OPKG_ERROR,
648 "Cannot find package %s.\n"
649 "Check the spelling or perhaps run 'opkg update'\n",
654 err = opkg_download_pkg(conf, pkg, ".");
657 opkg_message(conf, OPKG_ERROR,
658 "Failed to download %s\n", pkg->name);
660 opkg_message(conf, OPKG_NOTICE,
661 "Downloaded %s as %s\n",
662 pkg->name, pkg->local_filename);
670 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
673 pkg_vec_t *available;
675 char *pkg_name = NULL;
680 available = pkg_vec_alloc();
681 pkg_hash_fetch_available(&conf->pkg_hash, available);
682 pkg_vec_sort(available, pkg_compare_names);
683 for (i=0; i < available->len; i++) {
684 pkg = available->pkgs[i];
685 /* if we have package name or pattern and pkg does not match, then skip it */
686 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
690 pkg_vec_free(available);
696 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
699 pkg_vec_t *available;
701 char *pkg_name = NULL;
706 available = pkg_vec_alloc();
707 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
708 pkg_vec_sort(available, pkg_compare_names);
709 for (i=0; i < available->len; i++) {
710 pkg = available->pkgs[i];
711 /* if we have package name or pattern and pkg does not match, then skip it */
712 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
717 pkg_vec_free(available);
722 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
724 struct active_list *head = prepare_upgrade_list(conf);
725 struct active_list *node=NULL;
726 pkg_t *_old_pkg, *_new_pkg;
728 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
729 _old_pkg = list_entry(node, pkg_t, list);
730 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
731 old_v = pkg_version_str_alloc(_old_pkg);
732 new_v = pkg_version_str_alloc(_new_pkg);
733 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
737 active_list_head_delete(head);
741 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
744 pkg_vec_t *available;
746 char *pkg_name = NULL;
752 available = pkg_vec_alloc();
754 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
756 pkg_hash_fetch_available(&conf->pkg_hash, available);
758 for (i=0; i < available->len; i++) {
759 pkg = available->pkgs[i];
760 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
764 pkg_formatted_info(stdout, pkg);
766 if (conf->verbosity > 1) {
767 conffile_list_elt_t *iter;
768 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
769 conffile_t *cf = (conffile_t *)iter->data;
770 int modified = conffile_has_been_modified(conf, cf);
772 opkg_message(conf, OPKG_NOTICE,
773 "conffile=%s md5sum=%s modified=%d\n",
774 cf->name, cf->value, modified);
778 pkg_vec_free(available);
783 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
785 return opkg_info_status_cmd(conf, argc, argv, 0);
788 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
790 return opkg_info_status_cmd(conf, argc, argv, 1);
793 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
798 char *pkg_name = NULL;
802 err = opkg_configure_packages (conf, pkg_name);
805 err = opkg_configure_packages (conf, NULL);
808 write_status_files_if_changed(conf);
813 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
819 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
820 err = glob(globpattern, 0, NULL, &globbuf);
826 opkg_message(conf, OPKG_NOTICE,
827 "The following packages in %s will now be installed.\n",
829 for (i = 0; i < globbuf.gl_pathc; i++) {
830 opkg_message(conf, OPKG_NOTICE,
831 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
833 opkg_message(conf, OPKG_NOTICE, "\n");
834 for (i = 0; i < globbuf.gl_pathc; i++) {
835 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
837 err = unlink(globbuf.gl_pathv[i]);
839 opkg_message(conf, OPKG_ERROR,
840 "%s: ERROR: failed to unlink %s: %s\n",
841 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
851 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
855 pkg_t *pkg_to_remove;
856 pkg_vec_t *available;
857 char *pkg_name = NULL;
859 signal(SIGINT, sigint_handler);
861 // ENH: Add the "no pkg removed" just in case.
865 pkg_info_preinstall_check(conf);
867 available = pkg_vec_alloc();
868 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
869 for (i=0; i < argc; i++) {
870 pkg_name = xcalloc(1, strlen(argv[i])+2);
871 strcpy(pkg_name,argv[i]);
872 for (a=0; a < available->len; a++) {
873 pkg = available->pkgs[a];
874 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
877 if (conf->restrict_to_default_dest) {
878 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
882 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
885 if (pkg_to_remove == NULL) {
886 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
889 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
890 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
893 opkg_remove_pkg(conf, pkg_to_remove,0);
898 pkg_vec_free(available);
900 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
902 int flagged_pkg_count = 0;
905 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
907 for (i = 0; i < installed_pkgs->len; i++) {
908 pkg_t *pkg = installed_pkgs->pkgs[i];
909 if (pkg->state_flag & SF_USER) {
912 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
913 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
916 if (!flagged_pkg_count) {
917 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
918 "so refusing to uninstall unflagged non-leaf packages\n");
922 /* find packages not flagged SF_USER (i.e., installed to
923 * satisfy a dependence) and not having any dependents, and
927 for (i = 0; i < installed_pkgs->len; i++) {
928 pkg_t *pkg = installed_pkgs->pkgs[i];
929 if (!(pkg->state_flag & SF_USER)
930 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
932 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
933 opkg_remove_pkg(conf, pkg,0);
938 pkg_vec_free(installed_pkgs);
942 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
944 write_status_files_if_changed(conf);
948 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
954 signal(SIGINT, sigint_handler);
956 pkg_info_preinstall_check(conf);
958 for (i=0; i < argc; i++) {
959 if (conf->restrict_to_default_dest) {
960 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
964 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
968 opkg_message(conf, OPKG_ERROR,
969 "Package %s is not installed.\n", argv[i]);
972 opkg_purge_pkg(conf, pkg);
975 write_status_files_if_changed(conf);
979 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
983 const char *flags = argv[0];
986 signal(SIGINT, sigint_handler);
988 for (i=1; i < argc; i++) {
989 if (conf->restrict_to_default_dest) {
990 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
994 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
998 opkg_message(conf, OPKG_ERROR,
999 "Package %s is not installed.\n", argv[i]);
1002 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1003 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1004 pkg->state_flag = pkg_state_flag_from_str(flags);
1006 /* pb_ asked this feature 03292004 */
1007 /* Actually I will use only this two, but this is an open for various status */
1008 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1009 pkg->state_status = pkg_state_status_from_str(flags);
1011 opkg_state_changed++;
1012 opkg_message(conf, OPKG_NOTICE,
1013 "Setting flags for package %s to %s\n",
1017 write_status_files_if_changed(conf);
1021 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1025 str_list_elt_t *iter;
1032 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1035 opkg_message(conf, OPKG_ERROR,
1036 "Package %s not installed.\n", argv[0]);
1040 files = pkg_get_installed_files(pkg);
1041 pkg_version = pkg_version_str_alloc(pkg);
1043 printf("Package %s (%s) is installed on %s and has the following files:\n",
1044 pkg->name, pkg_version, pkg->dest->name);
1046 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
1047 printf("%s\n", (char *)iter->data);
1050 pkg_free_installed_files(pkg);
1055 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1059 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1060 const char *rel_str = "depends on";
1063 pkg_info_preinstall_check(conf);
1065 if (conf->query_all)
1066 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1068 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1069 for (i = 0; i < argc; i++) {
1070 const char *target = argv[i];
1073 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1075 for (j = 0; j < available_pkgs->len; j++) {
1076 pkg_t *pkg = available_pkgs->pkgs[j];
1077 if (fnmatch(target, pkg->name, 0) == 0) {
1079 int count = pkg->depends_count + pkg->pre_depends_count;
1080 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1081 target, pkg->architecture, rel_str);
1082 for (k = 0; k < count; k++) {
1083 compound_depend_t *cdepend = &pkg->depends[k];
1085 for (l = 0; l < cdepend->possibility_count; l++) {
1086 depend_t *possibility = cdepend->possibilities[l];
1087 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1088 if (conf->verbosity > 0) {
1089 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1090 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1091 if (possibility->version) {
1092 char *typestr = NULL;
1093 switch (possibility->constraint) {
1094 case NONE: typestr = "none"; break;
1095 case EARLIER: typestr = "<"; break;
1096 case EARLIER_EQUAL: typestr = "<="; break;
1097 case EQUAL: typestr = "="; break;
1098 case LATER_EQUAL: typestr = ">="; break;
1099 case LATER: typestr = ">"; break;
1101 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1105 opkg_message(conf, OPKG_ERROR, "\n");
1111 pkg_vec_free(available_pkgs);
1116 enum what_field_type {
1125 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1129 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1130 const char *rel_str = NULL;
1134 switch (what_field_type) {
1135 case WHATDEPENDS: rel_str = "depends on"; break;
1136 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1137 case WHATSUGGESTS: rel_str = "suggests"; break;
1138 case WHATRECOMMENDS: rel_str = "recommends"; break;
1139 case WHATPROVIDES: rel_str = "provides"; break;
1140 case WHATREPLACES: rel_str = "replaces"; break;
1143 if (conf->query_all)
1144 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1146 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1148 /* mark the root set */
1149 pkg_vec_clear_marks(available_pkgs);
1150 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1151 for (i = 0; i < argc; i++) {
1152 const char *dependee_pattern = argv[i];
1153 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1155 for (i = 0; i < available_pkgs->len; i++) {
1156 pkg_t *pkg = available_pkgs->pkgs[i];
1157 if (pkg->state_flag & SF_MARKED) {
1158 /* mark the parent (abstract) package */
1159 pkg_mark_provides(pkg);
1160 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1164 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1169 for (j = 0; j < available_pkgs->len; j++) {
1170 pkg_t *pkg = available_pkgs->pkgs[j];
1172 int count = ((what_field_type == WHATCONFLICTS)
1173 ? pkg->conflicts_count
1174 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1175 /* skip this package if it is already marked */
1176 if (pkg->parent->state_flag & SF_MARKED) {
1179 for (k = 0; k < count; k++) {
1180 compound_depend_t *cdepend =
1181 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1183 for (l = 0; l < cdepend->possibility_count; l++) {
1184 depend_t *possibility = cdepend->possibilities[l];
1185 if (possibility->pkg->state_flag & SF_MARKED) {
1186 /* mark the depending package so we won't visit it again */
1187 pkg->state_flag |= SF_MARKED;
1188 pkg_mark_provides(pkg);
1191 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1192 if (conf->verbosity > 0) {
1193 char *ver = pkg_version_str_alloc(pkg);
1194 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1195 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1196 if (possibility->version) {
1197 char *typestr = NULL;
1198 switch (possibility->constraint) {
1199 case NONE: typestr = "none"; break;
1200 case EARLIER: typestr = "<"; break;
1201 case EARLIER_EQUAL: typestr = "<="; break;
1202 case EQUAL: typestr = "="; break;
1203 case LATER_EQUAL: typestr = ">="; break;
1204 case LATER: typestr = ">"; break;
1206 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1209 if (!pkg_dependence_satisfiable(conf, possibility))
1210 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1212 opkg_message(conf, OPKG_NOTICE, "\n");
1220 } while (changed && recursive);
1221 pkg_vec_free(available_pkgs);
1227 static int pkg_mark_provides(pkg_t *pkg)
1229 int provides_count = pkg->provides_count;
1230 abstract_pkg_t **provides = pkg->provides;
1232 pkg->parent->state_flag |= SF_MARKED;
1233 for (i = 0; i < provides_count; i++) {
1234 provides[i]->state_flag |= SF_MARKED;
1239 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1241 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1243 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1245 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1248 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1250 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1253 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1255 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1258 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1260 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1263 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1267 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1268 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1271 pkg_info_preinstall_check(conf);
1273 if (conf->query_all)
1274 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1276 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1277 for (i = 0; i < argc; i++) {
1278 const char *target = argv[i];
1281 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1283 for (j = 0; j < available_pkgs->len; j++) {
1284 pkg_t *pkg = available_pkgs->pkgs[j];
1286 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1287 for (k = 0; k < count; k++) {
1288 abstract_pkg_t *apkg =
1289 ((what_field_type == WHATPROVIDES)
1291 : pkg->replaces[k]);
1292 if (fnmatch(target, apkg->name, 0) == 0) {
1293 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1294 if (strcmp(target, apkg->name) != 0)
1295 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1296 opkg_message(conf, OPKG_ERROR, "\n");
1301 pkg_vec_free(available_pkgs);
1306 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1308 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1311 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1313 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1316 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1320 pkg_vec_t *installed;
1322 str_list_t *installed_files;
1323 str_list_elt_t *iter;
1324 char *installed_file;
1330 installed = pkg_vec_alloc();
1331 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1332 pkg_vec_sort(installed, pkg_compare_names);
1334 for (i=0; i < installed->len; i++) {
1335 pkg = installed->pkgs[i];
1337 installed_files = pkg_get_installed_files(pkg);
1339 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1340 installed_file = (char *)iter->data;
1341 if (fnmatch(argv[0], installed_file, 0)==0)
1345 pkg_free_installed_files(pkg);
1348 pkg_vec_free(installed);
1353 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1356 /* this is a bit gross */
1358 parseVersion(&p1, argv[0]);
1359 parseVersion(&p2, argv[2]);
1360 return pkg_version_satisfied(&p1, &p2, argv[1]);
1362 opkg_message(conf, OPKG_ERROR,
1363 "opkg compare_versions <v1> <op> <v2>\n"
1364 "<op> is one of <= >= << >> =\n");
1369 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1371 nv_pair_list_elt_t *l;
1373 list_for_each_entry(l, &conf->arch_list.head, node) {
1374 nv_pair_t *nv = (nv_pair_t *)l->data;
1375 printf("arch %s %s\n", nv->name, nv->value);