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;
772 available = pkg_vec_alloc();
774 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
776 pkg_hash_fetch_available(&conf->pkg_hash, available);
778 for (i=0; i < available->len; i++) {
779 pkg = available->pkgs[i];
780 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
784 pkg_info = pkg_formatted_info(pkg);
785 if (pkg_info == NULL)
788 printf("%s\n", pkg_info);
791 if (conf->verbosity > 1) {
792 conffile_list_elt_t *iter;
793 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
794 conffile_t *cf = (conffile_t *)iter->data;
795 int modified = conffile_has_been_modified(conf, cf);
796 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
797 cf->name, cf->value, modified);
801 pkg_vec_free(available);
806 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
808 return opkg_info_status_cmd(conf, argc, argv, 0);
811 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
813 return opkg_info_status_cmd(conf, argc, argv, 1);
816 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
821 char *pkg_name = NULL;
825 err = opkg_configure_packages (conf, pkg_name);
828 err = opkg_configure_packages (conf, NULL);
831 write_status_files_if_changed(conf);
836 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
842 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
843 err = glob(globpattern, 0, NULL, &globbuf);
849 opkg_message(conf, OPKG_NOTICE,
850 "The following packages in %s will now be installed.\n",
852 for (i = 0; i < globbuf.gl_pathc; i++) {
853 opkg_message(conf, OPKG_NOTICE,
854 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
856 opkg_message(conf, OPKG_NOTICE, "\n");
857 for (i = 0; i < globbuf.gl_pathc; i++) {
858 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
860 err = unlink(globbuf.gl_pathv[i]);
862 opkg_message(conf, OPKG_ERROR,
863 "%s: ERROR: failed to unlink %s: %s\n",
864 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
874 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
878 pkg_t *pkg_to_remove;
879 pkg_vec_t *available;
880 char *pkg_name = NULL;
882 signal(SIGINT, sigint_handler);
884 // ENH: Add the "no pkg removed" just in case.
888 pkg_info_preinstall_check(conf);
890 available = pkg_vec_alloc();
891 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
892 for (i=0; i < argc; i++) {
893 pkg_name = calloc(1, strlen(argv[i])+2);
894 strcpy(pkg_name,argv[i]);
895 for (a=0; a < available->len; a++) {
896 pkg = available->pkgs[a];
897 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
900 if (conf->restrict_to_default_dest) {
901 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
905 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
908 if (pkg_to_remove == NULL) {
909 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
912 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
913 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
916 opkg_remove_pkg(conf, pkg_to_remove,0);
921 pkg_vec_free(available);
923 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
925 int flagged_pkg_count = 0;
928 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
930 for (i = 0; i < installed_pkgs->len; i++) {
931 pkg_t *pkg = installed_pkgs->pkgs[i];
932 if (pkg->state_flag & SF_USER) {
935 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
936 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
939 if (!flagged_pkg_count) {
940 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
941 "so refusing to uninstall unflagged non-leaf packages\n");
945 /* find packages not flagged SF_USER (i.e., installed to
946 * satisfy a dependence) and not having any dependents, and
950 for (i = 0; i < installed_pkgs->len; i++) {
951 pkg_t *pkg = installed_pkgs->pkgs[i];
952 if (!(pkg->state_flag & SF_USER)
953 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
955 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
956 opkg_remove_pkg(conf, pkg,0);
961 pkg_vec_free(installed_pkgs);
965 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
967 write_status_files_if_changed(conf);
971 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
977 signal(SIGINT, sigint_handler);
979 pkg_info_preinstall_check(conf);
981 for (i=0; i < argc; i++) {
982 if (conf->restrict_to_default_dest) {
983 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
987 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
991 opkg_message(conf, OPKG_ERROR,
992 "Package %s is not installed.\n", argv[i]);
995 opkg_purge_pkg(conf, pkg);
998 write_status_files_if_changed(conf);
1002 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1006 const char *flags = argv[0];
1009 signal(SIGINT, sigint_handler);
1011 for (i=1; i < argc; i++) {
1012 if (conf->restrict_to_default_dest) {
1013 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1015 conf->default_dest);
1017 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1021 opkg_message(conf, OPKG_ERROR,
1022 "Package %s is not installed.\n", argv[i]);
1025 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1026 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1027 pkg->state_flag = pkg_state_flag_from_str(flags);
1029 /* pb_ asked this feature 03292004 */
1030 /* Actually I will use only this two, but this is an open for various status */
1031 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1032 pkg->state_status = pkg_state_status_from_str(flags);
1034 opkg_state_changed++;
1035 opkg_message(conf, OPKG_NOTICE,
1036 "Setting flags for package %s to %s\n",
1040 write_status_files_if_changed(conf);
1044 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1048 str_list_elt_t *iter;
1055 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1058 opkg_message(conf, OPKG_ERROR,
1059 "Package %s not installed.\n", argv[0]);
1063 files = pkg_get_installed_files(pkg);
1064 pkg_version = pkg_version_str_alloc(pkg);
1066 printf("Package %s (%s) is installed on %s and has the following files:\n",
1067 pkg->name, pkg_version, pkg->dest->name);
1069 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
1070 printf("%s\n", (char *)iter->data);
1073 pkg_free_installed_files(pkg);
1078 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1082 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1083 const char *rel_str = "depends on";
1086 pkg_info_preinstall_check(conf);
1088 if (conf->query_all)
1089 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1091 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1092 for (i = 0; i < argc; i++) {
1093 const char *target = argv[i];
1096 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1098 for (j = 0; j < available_pkgs->len; j++) {
1099 pkg_t *pkg = available_pkgs->pkgs[j];
1100 if (fnmatch(target, pkg->name, 0) == 0) {
1102 int count = pkg->depends_count + pkg->pre_depends_count;
1103 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1104 target, pkg->architecture, rel_str);
1105 for (k = 0; k < count; k++) {
1106 compound_depend_t *cdepend = &pkg->depends[k];
1108 for (l = 0; l < cdepend->possibility_count; l++) {
1109 depend_t *possibility = cdepend->possibilities[l];
1110 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1111 if (conf->verbosity > 0) {
1112 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1113 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1114 if (possibility->version) {
1115 char *typestr = NULL;
1116 switch (possibility->constraint) {
1117 case NONE: typestr = "none"; break;
1118 case EARLIER: typestr = "<"; break;
1119 case EARLIER_EQUAL: typestr = "<="; break;
1120 case EQUAL: typestr = "="; break;
1121 case LATER_EQUAL: typestr = ">="; break;
1122 case LATER: typestr = ">"; break;
1124 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1128 opkg_message(conf, OPKG_ERROR, "\n");
1134 pkg_vec_free(available_pkgs);
1139 enum what_field_type {
1148 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1152 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1153 const char *rel_str = NULL;
1157 switch (what_field_type) {
1158 case WHATDEPENDS: rel_str = "depends on"; break;
1159 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1160 case WHATSUGGESTS: rel_str = "suggests"; break;
1161 case WHATRECOMMENDS: rel_str = "recommends"; break;
1162 case WHATPROVIDES: rel_str = "provides"; break;
1163 case WHATREPLACES: rel_str = "replaces"; break;
1166 if (conf->query_all)
1167 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1169 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1171 /* mark the root set */
1172 pkg_vec_clear_marks(available_pkgs);
1173 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1174 for (i = 0; i < argc; i++) {
1175 const char *dependee_pattern = argv[i];
1176 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1178 for (i = 0; i < available_pkgs->len; i++) {
1179 pkg_t *pkg = available_pkgs->pkgs[i];
1180 if (pkg->state_flag & SF_MARKED) {
1181 /* mark the parent (abstract) package */
1182 pkg_mark_provides(pkg);
1183 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1187 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1192 for (j = 0; j < available_pkgs->len; j++) {
1193 pkg_t *pkg = available_pkgs->pkgs[j];
1195 int count = ((what_field_type == WHATCONFLICTS)
1196 ? pkg->conflicts_count
1197 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1198 /* skip this package if it is already marked */
1199 if (pkg->parent->state_flag & SF_MARKED) {
1202 for (k = 0; k < count; k++) {
1203 compound_depend_t *cdepend =
1204 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1206 for (l = 0; l < cdepend->possibility_count; l++) {
1207 depend_t *possibility = cdepend->possibilities[l];
1208 if (possibility->pkg->state_flag & SF_MARKED) {
1209 /* mark the depending package so we won't visit it again */
1210 pkg->state_flag |= SF_MARKED;
1211 pkg_mark_provides(pkg);
1214 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1215 if (conf->verbosity > 0) {
1216 char *ver = pkg_version_str_alloc(pkg);
1217 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1218 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1219 if (possibility->version) {
1220 char *typestr = NULL;
1221 switch (possibility->constraint) {
1222 case NONE: typestr = "none"; break;
1223 case EARLIER: typestr = "<"; break;
1224 case EARLIER_EQUAL: typestr = "<="; break;
1225 case EQUAL: typestr = "="; break;
1226 case LATER_EQUAL: typestr = ">="; break;
1227 case LATER: typestr = ">"; break;
1229 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1232 if (!pkg_dependence_satisfiable(conf, possibility))
1233 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1235 opkg_message(conf, OPKG_NOTICE, "\n");
1243 } while (changed && recursive);
1244 pkg_vec_free(available_pkgs);
1250 static int pkg_mark_provides(pkg_t *pkg)
1252 int provides_count = pkg->provides_count;
1253 abstract_pkg_t **provides = pkg->provides;
1255 pkg->parent->state_flag |= SF_MARKED;
1256 for (i = 0; i < provides_count; i++) {
1257 provides[i]->state_flag |= SF_MARKED;
1262 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1264 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1266 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1268 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1271 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1273 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1276 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1278 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1281 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1283 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1286 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1290 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1291 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1294 pkg_info_preinstall_check(conf);
1296 if (conf->query_all)
1297 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1299 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1300 for (i = 0; i < argc; i++) {
1301 const char *target = argv[i];
1304 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1306 for (j = 0; j < available_pkgs->len; j++) {
1307 pkg_t *pkg = available_pkgs->pkgs[j];
1309 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1310 for (k = 0; k < count; k++) {
1311 abstract_pkg_t *apkg =
1312 ((what_field_type == WHATPROVIDES)
1314 : pkg->replaces[k]);
1315 if (fnmatch(target, apkg->name, 0) == 0) {
1316 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1317 if (strcmp(target, apkg->name) != 0)
1318 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1319 opkg_message(conf, OPKG_ERROR, "\n");
1324 pkg_vec_free(available_pkgs);
1329 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1331 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1334 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1336 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1339 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1343 pkg_vec_t *installed;
1345 str_list_t *installed_files;
1346 str_list_elt_t *iter;
1347 char *installed_file;
1353 installed = pkg_vec_alloc();
1354 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1355 pkg_vec_sort(installed, pkg_compare_names);
1357 for (i=0; i < installed->len; i++) {
1358 pkg = installed->pkgs[i];
1360 installed_files = pkg_get_installed_files(pkg);
1362 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1363 installed_file = (char *)iter->data;
1364 if (fnmatch(argv[0], installed_file, 0)==0)
1368 pkg_free_installed_files(pkg);
1371 pkg_vec_free(installed);
1376 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1379 /* this is a bit gross */
1381 parseVersion(&p1, argv[0]);
1382 parseVersion(&p2, argv[2]);
1383 return pkg_version_satisfied(&p1, &p2, argv[1]);
1385 opkg_message(conf, OPKG_ERROR,
1386 "opkg compare_versions <v1> <op> <v2>\n"
1387 "<op> is one of <= >= << >> =\n");
1392 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1394 nv_pair_list_elt_t *l;
1396 list_for_each_entry(l, &conf->arch_list.head, node) {
1397 nv_pair_t *nv = (nv_pair_t *)l->data;
1398 printf("arch %s %s\n", nv->name, nv->value);