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.
24 #include "opkg_conf.h"
26 #include "opkg_message.h"
29 #include "pkg_parse.h"
30 #include "sprintf_alloc.h"
32 #include "file_util.h"
33 #include "libbb/libbb.h"
34 #include "opkg_utils.h"
35 #include "opkg_defines.h"
36 #include "opkg_download.h"
37 #include "opkg_install.h"
38 #include "opkg_upgrade.h"
39 #include "opkg_remove.h"
40 #include "opkg_configure.h"
41 #include "opkg_message.h"
45 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv);
46 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv);
47 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv);
48 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv);
49 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv);
50 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv);
51 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv);
52 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv);
53 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
54 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
55 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
56 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
57 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
58 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int pkg_mark_provides(pkg_t *pkg);
71 /* XXX: CLEANUP: The usage strings should be incorporated into this
72 array for easier maintenance */
73 static opkg_cmd_t cmds[] = {
74 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
75 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
76 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
77 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
78 {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
79 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
80 {"list-upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
81 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
82 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
83 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
84 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
85 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
86 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
87 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
88 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
89 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
90 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
91 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
92 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
93 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
94 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
95 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
96 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
97 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
98 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
99 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
100 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
101 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
102 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
103 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
106 static void print_pkg(pkg_t *pkg)
108 char *version = pkg_version_str_alloc(pkg);
109 if (pkg->description)
110 printf("%s - %s - %s\n", pkg->name, version, pkg->description);
112 printf("%s - %s\n", pkg->name, version);
116 int opkg_state_changed;
117 static void write_status_files_if_changed(opkg_conf_t *conf)
119 if (opkg_state_changed && !conf->noaction) {
120 opkg_message(conf, OPKG_INFO,
121 " writing status file\n");
122 opkg_conf_write_status_files(conf);
123 pkg_write_changed_filelists(conf);
125 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
130 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
132 opkg_cmd_t *opkg_cmd_find(const char *name)
137 for (i=0; i < num_cmds; i++) {
139 if (strcmp(name, cmd->name) == 0) {
147 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
151 result = (cmd->fun)(conf, argc, argv);
159 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
165 pkg_src_list_elt_t *iter;
169 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
171 if (! file_is_dir(lists_dir)) {
172 if (file_exists(lists_dir)) {
173 opkg_message(conf, OPKG_ERROR,
174 "%s: ERROR: %s exists, but is not a directory\n",
175 __FUNCTION__, lists_dir);
179 err = file_mkdir_hier(lists_dir, 0755);
181 opkg_message(conf, OPKG_ERROR,
182 "%s: ERROR: failed to make directory %s: %s\n",
183 __FUNCTION__, lists_dir, strerror(errno));
191 sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
192 if (mkdtemp (tmp) == NULL) {
198 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
199 char *url, *list_file_name;
201 src = (pkg_src_t *)iter->data;
203 if (src->extra_data) /* debian style? */
204 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
205 src->gzip ? "Packages.gz" : "Packages");
207 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
209 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
214 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
215 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
217 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
218 in = fopen (tmp_file_name, "r");
219 out = fopen (list_file_name, "w");
228 unlink (tmp_file_name);
232 err = opkg_download(conf, url, list_file_name, NULL, NULL);
236 opkg_message(conf, OPKG_NOTICE,
237 "Updated list of available packages in %s\n",
241 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
242 if (conf->check_signature) {
243 /* download detached signitures to verify the package lists */
244 /* get the url for the sig file */
245 if (src->extra_data) /* debian style? */
246 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
249 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
251 /* create temporary file for it */
254 /* Put the signature in the right place */
255 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
257 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
260 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
263 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
265 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
267 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
269 /* We shouldn't unlink the signature ! */
270 // unlink (tmp_file_name);
271 free (tmp_file_name);
277 free(list_file_name);
287 struct opkg_intercept
293 typedef struct opkg_intercept *opkg_intercept_t;
295 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
297 opkg_intercept_t ctx;
300 ctx = xcalloc(1, sizeof (*ctx));
301 ctx->oldpath = xstrdup(getenv("PATH"));
302 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
303 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX", conf->tmp_dir);
305 if (mkdtemp(ctx->statedir) == NULL) {
306 fprintf(stderr, "%s: mkdtemp: %s\n", __FUNCTION__, strerror(errno));
314 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
315 setenv("PATH", newpath, 1);
321 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
326 setenv ("PATH", ctx->oldpath, 1);
329 dir = opendir (ctx->statedir);
332 while (de = readdir (dir), de != NULL) {
335 if (de->d_name[0] == '.')
338 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
339 if (access (path, X_OK) == 0) {
340 const char *argv[] = {"sh", "-c", path, NULL};
347 perror (ctx->statedir);
350 free (ctx->statedir);
356 /* For package pkg do the following: If it is already visited, return. If not,
357 add it in visited list and recurse to its deps. Finally, add it to ordered
359 pkg_vec all contains all available packages in repos.
360 pkg_vec visited contains packages already visited by this function, and is
361 used to end recursion and avoid an infinite loop on graph cycles.
362 pkg_vec ordered will finally contain the ordered set of packages.
364 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
365 pkg_vec_t *visited, pkg_vec_t *ordered)
370 compound_depend_t * compound_depend;
371 depend_t ** possible_satisfiers;
372 abstract_pkg_t *abpkg;
373 abstract_pkg_t **dependents;
375 /* If it's just an available package, that is, not installed and not even
377 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
378 would do here. However, if there is an intermediate node (pkg) that is
379 configured and installed between two unpacked packages, the latter
380 won't be properly reordered, unless all installed/unpacked pkgs are
382 if (pkg->state_status == SS_NOT_INSTALLED)
385 /* If the package has already been visited (by this function), skip it */
386 for(j = 0; j < visited->len; j++)
387 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
388 opkg_message(conf, OPKG_INFO,
389 " pkg: %s already visited\n", pkg->name);
393 pkg_vec_insert(visited, pkg);
395 count = pkg->pre_depends_count + pkg->depends_count + \
396 pkg->recommends_count + pkg->suggests_count;
398 opkg_message(conf, OPKG_INFO,
399 " pkg: %s\n", pkg->name);
401 /* Iterate over all the dependencies of pkg. For each one, find a package
402 that is either installed or unpacked and satisfies this dependency.
403 (there should only be one such package per dependency installed or
404 unpacked). Then recurse to the dependency package */
405 for (j=0; j < count ; j++) {
406 compound_depend = &pkg->depends[j];
407 possible_satisfiers = compound_depend->possibilities;
408 for (k=0; k < compound_depend->possibility_count ; k++) {
409 abpkg = possible_satisfiers[k]->pkg;
410 dependents = abpkg->provided_by->pkgs;
412 if (dependents != NULL)
413 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
414 opkg_message(conf, OPKG_INFO,
415 " Descending on pkg: %s\n",
416 dependents [l]->name);
418 /* find whether dependent l is installed or unpacked,
419 * and then find which package in the list satisfies it */
420 for(m = 0; m < all->len; m++) {
422 if ( dep->state_status != SS_NOT_INSTALLED)
423 if ( ! strcmp(dep->name, dependents[l]->name)) {
424 opkg_recurse_pkgs_in_order(conf, dep, all,
426 /* Stop the outer loop */
427 l = abpkg->provided_by->len;
428 /* break from the inner loop */
437 /* When all recursions from this node down, are over, and all
438 dependencies have been added in proper order in the ordered array, add
439 also the package pkg to ordered array */
440 pkg_vec_insert(ordered, pkg);
446 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
448 pkg_vec_t *all, *ordered, *visited;
454 opkg_message(conf, OPKG_INFO,
455 "Configuring unpacked packages\n");
458 all = pkg_vec_alloc();
460 pkg_hash_fetch_available(&conf->pkg_hash, all);
462 /* Reorder pkgs in order to be configured according to the Depends: tag
464 opkg_message(conf, OPKG_INFO,
465 "Reordering packages before configuring them...\n");
466 ordered = pkg_vec_alloc();
467 visited = pkg_vec_alloc();
468 for(i = 0; i < all->len; i++) {
470 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
473 ic = opkg_prep_intercepts (conf);
479 for(i = 0; i < all->len; i++) {
482 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
485 if (pkg->state_status == SS_UNPACKED) {
486 opkg_message(conf, OPKG_NOTICE,
487 "Configuring %s\n", pkg->name);
489 r = opkg_configure(conf, pkg);
491 pkg->state_status = SS_INSTALLED;
492 pkg->parent->state_status = SS_INSTALLED;
493 pkg->state_flag &= ~SF_PREFER;
501 r = opkg_finalize_intercepts (ic);
507 pkg_vec_free(ordered);
508 pkg_vec_free(visited);
513 static opkg_conf_t *global_conf;
515 static void sigint_handler(int sig)
517 signal(sig, SIG_DFL);
518 opkg_message(NULL, OPKG_NOTICE,
519 "opkg: interrupted. writing out status database\n");
520 write_status_files_if_changed(global_conf);
524 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
531 signal(SIGINT, sigint_handler);
534 * Now scan through package names and install
536 for (i=0; i < argc; i++) {
539 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
540 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
544 pkg_info_preinstall_check(conf);
546 for (i=0; i < argc; i++) {
548 err = opkg_install_by_name(conf, arg);
550 opkg_message(conf, OPKG_ERROR, "Cannot find package %s.\n", arg);
554 opkg_configure_packages(conf, NULL);
556 write_status_files_if_changed(conf);
561 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
568 signal(SIGINT, sigint_handler);
571 for (i=0; i < argc; i++) {
574 err = opkg_prepare_url_for_install(conf, arg, &arg);
578 pkg_info_preinstall_check(conf);
580 for (i=0; i < argc; i++) {
582 if (conf->restrict_to_default_dest) {
583 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
587 opkg_message(conf, OPKG_NOTICE,
588 "Package %s not installed in %s\n",
589 argv[i], conf->default_dest->name);
593 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
597 opkg_upgrade_pkg(conf, pkg);
599 opkg_install_by_name(conf, arg);
603 pkg_vec_t *installed = pkg_vec_alloc();
605 pkg_info_preinstall_check(conf);
607 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
608 for (i = 0; i < installed->len; i++) {
609 pkg = installed->pkgs[i];
610 opkg_upgrade_pkg(conf, pkg);
612 pkg_vec_free(installed);
615 opkg_configure_packages(conf, NULL);
617 write_status_files_if_changed(conf);
622 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
628 pkg_info_preinstall_check(conf);
629 for (i = 0; i < argc; i++) {
632 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
634 opkg_message(conf, OPKG_ERROR,
635 "Cannot find package %s.\n"
636 "Check the spelling or perhaps run 'opkg update'\n",
641 err = opkg_download_pkg(conf, pkg, ".");
644 opkg_message(conf, OPKG_ERROR,
645 "Failed to download %s\n", pkg->name);
647 opkg_message(conf, OPKG_NOTICE,
648 "Downloaded %s as %s\n",
649 pkg->name, pkg->local_filename);
657 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
660 pkg_vec_t *available;
662 char *pkg_name = NULL;
667 available = pkg_vec_alloc();
668 pkg_hash_fetch_available(&conf->pkg_hash, available);
669 pkg_vec_sort(available, pkg_compare_names);
670 for (i=0; i < available->len; i++) {
671 pkg = available->pkgs[i];
672 /* if we have package name or pattern and pkg does not match, then skip it */
673 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
677 pkg_vec_free(available);
683 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
686 pkg_vec_t *available;
688 char *pkg_name = NULL;
693 available = pkg_vec_alloc();
694 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
695 pkg_vec_sort(available, pkg_compare_names);
696 for (i=0; i < available->len; i++) {
697 pkg = available->pkgs[i];
698 /* if we have package name or pattern and pkg does not match, then skip it */
699 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
704 pkg_vec_free(available);
709 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
711 struct active_list *head = prepare_upgrade_list(conf);
712 struct active_list *node=NULL;
713 pkg_t *_old_pkg, *_new_pkg;
715 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
716 _old_pkg = list_entry(node, pkg_t, list);
717 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
718 old_v = pkg_version_str_alloc(_old_pkg);
719 new_v = pkg_version_str_alloc(_new_pkg);
720 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
724 active_list_head_delete(head);
728 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
731 pkg_vec_t *available;
733 char *pkg_name = NULL;
739 available = pkg_vec_alloc();
741 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
743 pkg_hash_fetch_available(&conf->pkg_hash, available);
745 for (i=0; i < available->len; i++) {
746 pkg = available->pkgs[i];
747 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
751 pkg_formatted_info(stdout, pkg);
753 if (conf->verbosity >= OPKG_NOTICE) {
754 conffile_list_elt_t *iter;
755 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
756 conffile_t *cf = (conffile_t *)iter->data;
757 int modified = conffile_has_been_modified(conf, cf);
759 opkg_message(conf, OPKG_INFO,
760 "conffile=%s md5sum=%s modified=%d\n",
761 cf->name, cf->value, modified);
765 pkg_vec_free(available);
770 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
772 return opkg_info_status_cmd(conf, argc, argv, 0);
775 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
777 return opkg_info_status_cmd(conf, argc, argv, 1);
780 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
785 char *pkg_name = NULL;
789 err = opkg_configure_packages (conf, pkg_name);
792 err = opkg_configure_packages (conf, NULL);
795 write_status_files_if_changed(conf);
800 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
804 pkg_t *pkg_to_remove;
805 pkg_vec_t *available;
810 signal(SIGINT, sigint_handler);
812 pkg_info_preinstall_check(conf);
814 available = pkg_vec_alloc();
815 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
817 for (i=0; i<argc; i++) {
818 for (a=0; a<available->len; a++) {
819 pkg = available->pkgs[a];
820 if (fnmatch(argv[i], pkg->name, 0)) {
823 if (conf->restrict_to_default_dest) {
824 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
828 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
831 if (pkg_to_remove == NULL) {
832 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
835 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
836 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
839 opkg_remove_pkg(conf, pkg_to_remove, 0);
844 pkg_vec_free(available);
847 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
849 write_status_files_if_changed(conf);
853 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
857 const char *flags = argv[0];
860 signal(SIGINT, sigint_handler);
862 for (i=1; i < argc; i++) {
863 if (conf->restrict_to_default_dest) {
864 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
868 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
872 opkg_message(conf, OPKG_ERROR,
873 "Package %s is not installed.\n", argv[i]);
876 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
877 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
878 pkg->state_flag = pkg_state_flag_from_str(flags);
882 * Useful if a package is installed in an offline_root, and
883 * should be configured by opkg-cl configure at a later date.
885 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
886 pkg->state_status = pkg_state_status_from_str(flags);
889 opkg_state_changed++;
890 opkg_message(conf, OPKG_NOTICE,
891 "Setting flags for package %s to %s\n",
895 write_status_files_if_changed(conf);
899 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
903 str_list_elt_t *iter;
910 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
913 opkg_message(conf, OPKG_ERROR,
914 "Package %s not installed.\n", argv[0]);
918 files = pkg_get_installed_files(conf, pkg);
919 pkg_version = pkg_version_str_alloc(pkg);
921 printf("Package %s (%s) is installed on %s and has the following files:\n",
922 pkg->name, pkg_version, pkg->dest->name);
924 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
925 printf("%s\n", (char *)iter->data);
928 pkg_free_installed_files(pkg);
933 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
937 pkg_vec_t *available_pkgs;
938 compound_depend_t *cdep;
942 pkg_info_preinstall_check(conf);
944 available_pkgs = pkg_vec_alloc();
946 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
948 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
950 for (i=0; i<argc; i++) {
951 for (j=0; j<available_pkgs->len; j++) {
952 pkg = available_pkgs->pkgs[j];
954 if (fnmatch(argv[i], pkg->name, 0) != 0)
957 depends_count = pkg->depends_count +
958 pkg->pre_depends_count +
959 pkg->recommends_count +
962 opkg_message(conf, OPKG_NOTICE, "%s depends on:\n",
965 for (k=0; k<depends_count; k++) {
966 cdep = &pkg->depends[k];
968 if (cdep->type != DEPEND)
971 str = pkg_depend_str(pkg, k);
972 opkg_message(conf, OPKG_NOTICE, "\t%s\n", str);
979 pkg_vec_free(available_pkgs);
983 enum what_field_type {
992 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum depend_type what_field_type, int recursive, int argc, char **argv)
994 depend_t *possibility;
995 compound_depend_t *cdep;
996 pkg_vec_t *available_pkgs;
1000 const char *rel_str = NULL;
1003 switch (what_field_type) {
1004 case DEPEND: rel_str = "depends on"; break;
1005 case CONFLICTS: rel_str = "conflicts with"; break;
1006 case SUGGEST: rel_str = "suggests"; break;
1007 case RECOMMEND: rel_str = "recommends"; break;
1011 available_pkgs = pkg_vec_alloc();
1013 if (conf->query_all)
1014 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1016 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1018 /* mark the root set */
1019 pkg_vec_clear_marks(available_pkgs);
1020 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1021 for (i = 0; i < argc; i++)
1022 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
1024 for (i = 0; i < available_pkgs->len; i++) {
1025 pkg = available_pkgs->pkgs[i];
1026 if (pkg->state_flag & SF_MARKED) {
1027 /* mark the parent (abstract) package */
1028 pkg_mark_provides(pkg);
1029 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1033 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1037 for (j=0; j<available_pkgs->len; j++) {
1039 pkg = available_pkgs->pkgs[j];
1040 count = ((what_field_type == CONFLICTS)
1041 ? pkg->conflicts_count
1042 : pkg->pre_depends_count +
1043 pkg->depends_count +
1044 pkg->recommends_count +
1045 pkg->suggests_count);
1047 /* skip this package if it is already marked */
1048 if (pkg->parent->state_flag & SF_MARKED)
1051 for (k=0; k<count; k++) {
1052 cdep = (what_field_type == CONFLICTS)
1053 ? &pkg->conflicts[k]
1056 if (what_field_type != cdep->type)
1059 for (l=0; l<cdep->possibility_count; l++) {
1060 possibility = cdep->possibilities[l];
1062 if ((possibility->pkg->state_flag
1067 /* mark the depending package so we
1068 * won't visit it again */
1069 pkg->state_flag |= SF_MARKED;
1070 pkg_mark_provides(pkg);
1073 ver = pkg_version_str_alloc(pkg);
1074 opkg_message(conf, OPKG_NOTICE,
1079 possibility->pkg->name);
1081 if (possibility->version) {
1082 opkg_message(conf, OPKG_NOTICE,
1084 constraint_to_str(possibility->constraint),
1085 possibility->version);
1087 if (!pkg_dependence_satisfiable(conf, possibility))
1088 opkg_message(conf, OPKG_NOTICE,
1090 opkg_message(conf, OPKG_NOTICE, "\n");
1097 } while (changed && recursive);
1099 pkg_vec_free(available_pkgs);
1104 static int pkg_mark_provides(pkg_t *pkg)
1106 int provides_count = pkg->provides_count;
1107 abstract_pkg_t **provides = pkg->provides;
1109 pkg->parent->state_flag |= SF_MARKED;
1110 for (i = 0; i < provides_count; i++) {
1111 provides[i]->state_flag |= SF_MARKED;
1116 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1118 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 1, argc, argv);
1120 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1122 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 0, argc, argv);
1125 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1127 return opkg_what_depends_conflicts_cmd(conf, SUGGEST, 0, argc, argv);
1130 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1132 return opkg_what_depends_conflicts_cmd(conf, RECOMMEND, 0, argc, argv);
1135 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1137 return opkg_what_depends_conflicts_cmd(conf, CONFLICTS, 0, argc, argv);
1140 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1144 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1145 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1148 pkg_info_preinstall_check(conf);
1150 if (conf->query_all)
1151 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1153 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1154 for (i = 0; i < argc; i++) {
1155 const char *target = argv[i];
1158 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1160 for (j = 0; j < available_pkgs->len; j++) {
1161 pkg_t *pkg = available_pkgs->pkgs[j];
1163 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1164 for (k = 0; k < count; k++) {
1165 abstract_pkg_t *apkg =
1166 ((what_field_type == WHATPROVIDES)
1168 : pkg->replaces[k]);
1169 if (fnmatch(target, apkg->name, 0) == 0) {
1170 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1171 if (strcmp(target, apkg->name) != 0)
1172 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1173 opkg_message(conf, OPKG_ERROR, "\n");
1178 pkg_vec_free(available_pkgs);
1183 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1185 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1188 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1190 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1193 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1197 pkg_vec_t *installed;
1199 str_list_t *installed_files;
1200 str_list_elt_t *iter;
1201 char *installed_file;
1207 installed = pkg_vec_alloc();
1208 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1209 pkg_vec_sort(installed, pkg_compare_names);
1211 for (i=0; i < installed->len; i++) {
1212 pkg = installed->pkgs[i];
1214 installed_files = pkg_get_installed_files(conf, pkg);
1216 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1217 installed_file = (char *)iter->data;
1218 if (fnmatch(argv[0], installed_file, 0)==0)
1222 pkg_free_installed_files(pkg);
1225 pkg_vec_free(installed);
1230 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1233 /* this is a bit gross */
1235 parse_version(&p1, argv[0]);
1236 parse_version(&p2, argv[2]);
1237 return pkg_version_satisfied(&p1, &p2, argv[1]);
1239 opkg_message(conf, OPKG_ERROR,
1240 "opkg compare_versions <v1> <op> <v2>\n"
1241 "<op> is one of <= >= << >> =\n");
1246 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1248 nv_pair_list_elt_t *l;
1250 list_for_each_entry(l, &conf->arch_list.head, node) {
1251 nv_pair_t *nv = (nv_pair_t *)l->data;
1252 printf("arch %s %s\n", nv->name, nv->value);