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);
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);
718 if (_new_pkg == NULL)
720 old_v = pkg_version_str_alloc(_old_pkg);
721 new_v = pkg_version_str_alloc(_new_pkg);
722 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
726 active_list_head_delete(head);
730 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
733 pkg_vec_t *available;
735 char *pkg_name = NULL;
741 available = pkg_vec_alloc();
743 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
745 pkg_hash_fetch_available(&conf->pkg_hash, available);
747 for (i=0; i < available->len; i++) {
748 pkg = available->pkgs[i];
749 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
753 pkg_formatted_info(stdout, pkg);
755 if (conf->verbosity >= OPKG_NOTICE) {
756 conffile_list_elt_t *iter;
757 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
758 conffile_t *cf = (conffile_t *)iter->data;
759 int modified = conffile_has_been_modified(conf, cf);
761 opkg_message(conf, OPKG_INFO,
762 "conffile=%s md5sum=%s modified=%d\n",
763 cf->name, cf->value, modified);
767 pkg_vec_free(available);
772 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
774 return opkg_info_status_cmd(conf, argc, argv, 0);
777 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
779 return opkg_info_status_cmd(conf, argc, argv, 1);
782 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
787 char *pkg_name = NULL;
791 err = opkg_configure_packages (conf, pkg_name);
794 err = opkg_configure_packages (conf, NULL);
797 write_status_files_if_changed(conf);
802 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
806 pkg_t *pkg_to_remove;
807 pkg_vec_t *available;
812 signal(SIGINT, sigint_handler);
814 pkg_info_preinstall_check(conf);
816 available = pkg_vec_alloc();
817 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
819 for (i=0; i<argc; i++) {
820 for (a=0; a<available->len; a++) {
821 pkg = available->pkgs[a];
822 if (fnmatch(argv[i], pkg->name, 0)) {
825 if (conf->restrict_to_default_dest) {
826 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
830 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
833 if (pkg_to_remove == NULL) {
834 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
837 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
838 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
841 opkg_remove_pkg(conf, pkg_to_remove, 0);
846 pkg_vec_free(available);
849 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
851 write_status_files_if_changed(conf);
855 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
859 const char *flags = argv[0];
862 signal(SIGINT, sigint_handler);
864 for (i=1; i < argc; i++) {
865 if (conf->restrict_to_default_dest) {
866 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
870 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
874 opkg_message(conf, OPKG_ERROR,
875 "Package %s is not installed.\n", argv[i]);
878 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
879 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
880 pkg->state_flag = pkg_state_flag_from_str(flags);
884 * Useful if a package is installed in an offline_root, and
885 * should be configured by opkg-cl configure at a later date.
887 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
888 pkg->state_status = pkg_state_status_from_str(flags);
891 opkg_state_changed++;
892 opkg_message(conf, OPKG_NOTICE,
893 "Setting flags for package %s to %s\n",
897 write_status_files_if_changed(conf);
901 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
905 str_list_elt_t *iter;
912 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
915 opkg_message(conf, OPKG_ERROR,
916 "Package %s not installed.\n", argv[0]);
920 files = pkg_get_installed_files(conf, pkg);
921 pkg_version = pkg_version_str_alloc(pkg);
923 printf("Package %s (%s) is installed on %s and has the following files:\n",
924 pkg->name, pkg_version, pkg->dest->name);
926 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
927 printf("%s\n", (char *)iter->data);
930 pkg_free_installed_files(pkg);
935 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
939 pkg_vec_t *available_pkgs;
940 compound_depend_t *cdep;
944 pkg_info_preinstall_check(conf);
946 available_pkgs = pkg_vec_alloc();
948 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
950 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
952 for (i=0; i<argc; i++) {
953 for (j=0; j<available_pkgs->len; j++) {
954 pkg = available_pkgs->pkgs[j];
956 if (fnmatch(argv[i], pkg->name, 0) != 0)
959 depends_count = pkg->depends_count +
960 pkg->pre_depends_count +
961 pkg->recommends_count +
964 opkg_message(conf, OPKG_NOTICE, "%s depends on:\n",
967 for (k=0; k<depends_count; k++) {
968 cdep = &pkg->depends[k];
970 if (cdep->type != DEPEND)
973 str = pkg_depend_str(pkg, k);
974 opkg_message(conf, OPKG_NOTICE, "\t%s\n", str);
981 pkg_vec_free(available_pkgs);
985 enum what_field_type {
994 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum depend_type what_field_type, int recursive, int argc, char **argv)
996 depend_t *possibility;
997 compound_depend_t *cdep;
998 pkg_vec_t *available_pkgs;
1002 const char *rel_str = NULL;
1005 switch (what_field_type) {
1006 case DEPEND: rel_str = "depends on"; break;
1007 case CONFLICTS: rel_str = "conflicts with"; break;
1008 case SUGGEST: rel_str = "suggests"; break;
1009 case RECOMMEND: rel_str = "recommends"; break;
1013 available_pkgs = pkg_vec_alloc();
1015 if (conf->query_all)
1016 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1018 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1020 /* mark the root set */
1021 pkg_vec_clear_marks(available_pkgs);
1022 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1023 for (i = 0; i < argc; i++)
1024 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
1026 for (i = 0; i < available_pkgs->len; i++) {
1027 pkg = available_pkgs->pkgs[i];
1028 if (pkg->state_flag & SF_MARKED) {
1029 /* mark the parent (abstract) package */
1030 pkg_mark_provides(pkg);
1031 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1035 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1039 for (j=0; j<available_pkgs->len; j++) {
1041 pkg = available_pkgs->pkgs[j];
1042 count = ((what_field_type == CONFLICTS)
1043 ? pkg->conflicts_count
1044 : pkg->pre_depends_count +
1045 pkg->depends_count +
1046 pkg->recommends_count +
1047 pkg->suggests_count);
1049 /* skip this package if it is already marked */
1050 if (pkg->parent->state_flag & SF_MARKED)
1053 for (k=0; k<count; k++) {
1054 cdep = (what_field_type == CONFLICTS)
1055 ? &pkg->conflicts[k]
1058 if (what_field_type != cdep->type)
1061 for (l=0; l<cdep->possibility_count; l++) {
1062 possibility = cdep->possibilities[l];
1064 if ((possibility->pkg->state_flag
1069 /* mark the depending package so we
1070 * won't visit it again */
1071 pkg->state_flag |= SF_MARKED;
1072 pkg_mark_provides(pkg);
1075 ver = pkg_version_str_alloc(pkg);
1076 opkg_message(conf, OPKG_NOTICE,
1081 possibility->pkg->name);
1083 if (possibility->version) {
1084 opkg_message(conf, OPKG_NOTICE,
1086 constraint_to_str(possibility->constraint),
1087 possibility->version);
1089 if (!pkg_dependence_satisfiable(conf, possibility))
1090 opkg_message(conf, OPKG_NOTICE,
1092 opkg_message(conf, OPKG_NOTICE, "\n");
1099 } while (changed && recursive);
1101 pkg_vec_free(available_pkgs);
1106 static int pkg_mark_provides(pkg_t *pkg)
1108 int provides_count = pkg->provides_count;
1109 abstract_pkg_t **provides = pkg->provides;
1111 pkg->parent->state_flag |= SF_MARKED;
1112 for (i = 0; i < provides_count; i++) {
1113 provides[i]->state_flag |= SF_MARKED;
1118 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1120 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 1, argc, argv);
1122 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1124 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 0, argc, argv);
1127 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1129 return opkg_what_depends_conflicts_cmd(conf, SUGGEST, 0, argc, argv);
1132 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1134 return opkg_what_depends_conflicts_cmd(conf, RECOMMEND, 0, argc, argv);
1137 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1139 return opkg_what_depends_conflicts_cmd(conf, CONFLICTS, 0, argc, argv);
1142 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1146 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1147 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1150 pkg_info_preinstall_check(conf);
1152 if (conf->query_all)
1153 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1155 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1156 for (i = 0; i < argc; i++) {
1157 const char *target = argv[i];
1160 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1162 for (j = 0; j < available_pkgs->len; j++) {
1163 pkg_t *pkg = available_pkgs->pkgs[j];
1165 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1166 for (k = 0; k < count; k++) {
1167 abstract_pkg_t *apkg =
1168 ((what_field_type == WHATPROVIDES)
1170 : pkg->replaces[k]);
1171 if (fnmatch(target, apkg->name, 0) == 0) {
1172 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1173 if (strcmp(target, apkg->name) != 0)
1174 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1175 opkg_message(conf, OPKG_ERROR, "\n");
1180 pkg_vec_free(available_pkgs);
1185 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1187 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1190 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1192 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1195 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1199 pkg_vec_t *installed;
1201 str_list_t *installed_files;
1202 str_list_elt_t *iter;
1203 char *installed_file;
1209 installed = pkg_vec_alloc();
1210 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1211 pkg_vec_sort(installed, pkg_compare_names);
1213 for (i=0; i < installed->len; i++) {
1214 pkg = installed->pkgs[i];
1216 installed_files = pkg_get_installed_files(conf, pkg);
1218 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1219 installed_file = (char *)iter->data;
1220 if (fnmatch(argv[0], installed_file, 0)==0)
1224 pkg_free_installed_files(pkg);
1227 pkg_vec_free(installed);
1232 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1235 /* this is a bit gross */
1237 parse_version(&p1, argv[0]);
1238 parse_version(&p2, argv[2]);
1239 return pkg_version_satisfied(&p1, &p2, argv[1]);
1241 opkg_message(conf, OPKG_ERROR,
1242 "opkg compare_versions <v1> <op> <v2>\n"
1243 "<op> is one of <= >= << >> =\n");
1248 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1250 nv_pair_list_elt_t *l;
1252 list_for_each_entry(l, &conf->arch_list.head, node) {
1253 nv_pair_t *nv = (nv_pair_t *)l->data;
1254 printf("arch %s %s\n", nv->name, nv->value);