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"
34 #include "libbb/libbb.h"
35 #include "opkg_utils.h"
36 #include "opkg_defines.h"
37 #include "opkg_download.h"
38 #include "opkg_install.h"
39 #include "opkg_upgrade.h"
40 #include "opkg_remove.h"
41 #include "opkg_configure.h"
42 #include "opkg_message.h"
46 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv);
47 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv);
48 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv);
49 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv);
50 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv);
51 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv);
52 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv);
53 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv);
54 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
55 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
56 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
57 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
58 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
70 static int pkg_mark_provides(pkg_t *pkg);
72 /* XXX: CLEANUP: The usage strings should be incorporated into this
73 array for easier maintenance */
74 static opkg_cmd_t cmds[] = {
75 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
76 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
77 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
78 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
79 {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
80 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
81 {"list-upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
82 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
83 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
84 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
85 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
86 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
87 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
88 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
89 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
90 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
91 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
92 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
93 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
94 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
95 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
96 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
97 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
98 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
99 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
100 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
101 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
102 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
103 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
104 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
107 static void print_pkg(pkg_t *pkg)
109 char *version = pkg_version_str_alloc(pkg);
110 if (pkg->description)
111 printf("%s - %s - %s\n", pkg->name, version, pkg->description);
113 printf("%s - %s\n", pkg->name, version);
117 int opkg_state_changed;
118 static void write_status_files_if_changed(opkg_conf_t *conf)
120 if (opkg_state_changed && !conf->noaction) {
121 opkg_message(conf, OPKG_INFO,
122 " writing status file\n");
123 opkg_conf_write_status_files(conf);
124 pkg_write_changed_filelists(conf);
126 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
131 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
133 opkg_cmd_t *opkg_cmd_find(const char *name)
138 for (i=0; i < num_cmds; i++) {
140 if (strcmp(name, cmd->name) == 0) {
148 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
152 result = (cmd->fun)(conf, argc, argv);
160 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
166 pkg_src_list_elt_t *iter;
170 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
172 if (! file_is_dir(lists_dir)) {
173 if (file_exists(lists_dir)) {
174 opkg_message(conf, OPKG_ERROR,
175 "%s: ERROR: %s exists, but is not a directory\n",
176 __FUNCTION__, lists_dir);
180 err = file_mkdir_hier(lists_dir, 0755);
182 opkg_message(conf, OPKG_ERROR,
183 "%s: ERROR: failed to make directory %s: %s\n",
184 __FUNCTION__, lists_dir, strerror(errno));
192 sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
193 if (mkdtemp (tmp) == NULL) {
199 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
200 char *url, *list_file_name;
202 src = (pkg_src_t *)iter->data;
204 if (src->extra_data) /* debian style? */
205 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
206 src->gzip ? "Packages.gz" : "Packages");
208 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
210 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
215 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
216 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
218 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
219 in = fopen (tmp_file_name, "r");
220 out = fopen (list_file_name, "w");
229 unlink (tmp_file_name);
233 err = opkg_download(conf, url, list_file_name, NULL, NULL);
237 opkg_message(conf, OPKG_NOTICE,
238 "Updated list of available packages in %s\n",
242 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
243 if (conf->check_signature) {
244 /* download detached signitures to verify the package lists */
245 /* get the url for the sig file */
246 if (src->extra_data) /* debian style? */
247 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
250 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
252 /* create temporary file for it */
255 /* Put the signature in the right place */
256 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
258 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
261 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
264 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
266 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
268 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
270 /* We shouldn't unlink the signature ! */
271 // unlink (tmp_file_name);
272 free (tmp_file_name);
278 free(list_file_name);
288 struct opkg_intercept
294 typedef struct opkg_intercept *opkg_intercept_t;
296 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
298 opkg_intercept_t ctx;
301 ctx = xcalloc(1, sizeof (*ctx));
302 ctx->oldpath = xstrdup(getenv("PATH"));
303 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
304 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX", conf->tmp_dir);
306 if (mkdtemp(ctx->statedir) == NULL) {
307 fprintf(stderr, "%s: mkdtemp: %s\n", __FUNCTION__, strerror(errno));
315 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
316 setenv("PATH", newpath, 1);
322 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
327 setenv ("PATH", ctx->oldpath, 1);
330 dir = opendir (ctx->statedir);
333 while (de = readdir (dir), de != NULL) {
336 if (de->d_name[0] == '.')
339 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
340 if (access (path, X_OK) == 0) {
341 const char *argv[] = {"sh", "-c", path, NULL};
348 perror (ctx->statedir);
351 free (ctx->statedir);
357 /* For package pkg do the following: If it is already visited, return. If not,
358 add it in visited list and recurse to its deps. Finally, add it to ordered
360 pkg_vec all contains all available packages in repos.
361 pkg_vec visited contains packages already visited by this function, and is
362 used to end recursion and avoid an infinite loop on graph cycles.
363 pkg_vec ordered will finally contain the ordered set of packages.
365 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
366 pkg_vec_t *visited, pkg_vec_t *ordered)
371 compound_depend_t * compound_depend;
372 depend_t ** possible_satisfiers;
373 abstract_pkg_t *abpkg;
374 abstract_pkg_t **dependents;
376 /* If it's just an available package, that is, not installed and not even
378 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
379 would do here. However, if there is an intermediate node (pkg) that is
380 configured and installed between two unpacked packages, the latter
381 won't be properly reordered, unless all installed/unpacked pkgs are
383 if (pkg->state_status == SS_NOT_INSTALLED)
386 /* If the package has already been visited (by this function), skip it */
387 for(j = 0; j < visited->len; j++)
388 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
389 opkg_message(conf, OPKG_INFO,
390 " pkg: %s already visited\n", pkg->name);
394 pkg_vec_insert(visited, pkg);
396 count = pkg->pre_depends_count + pkg->depends_count + \
397 pkg->recommends_count + pkg->suggests_count;
399 opkg_message(conf, OPKG_INFO,
400 " pkg: %s\n", pkg->name);
402 /* Iterate over all the dependencies of pkg. For each one, find a package
403 that is either installed or unpacked and satisfies this dependency.
404 (there should only be one such package per dependency installed or
405 unpacked). Then recurse to the dependency package */
406 for (j=0; j < count ; j++) {
407 compound_depend = &pkg->depends[j];
408 possible_satisfiers = compound_depend->possibilities;
409 for (k=0; k < compound_depend->possibility_count ; k++) {
410 abpkg = possible_satisfiers[k]->pkg;
411 dependents = abpkg->provided_by->pkgs;
413 if (dependents != NULL)
414 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
415 opkg_message(conf, OPKG_INFO,
416 " Descending on pkg: %s\n",
417 dependents [l]->name);
419 /* find whether dependent l is installed or unpacked,
420 * and then find which package in the list satisfies it */
421 for(m = 0; m < all->len; m++) {
423 if ( dep->state_status != SS_NOT_INSTALLED)
424 if ( ! strcmp(dep->name, dependents[l]->name)) {
425 opkg_recurse_pkgs_in_order(conf, dep, all,
427 /* Stop the outer loop */
428 l = abpkg->provided_by->len;
429 /* break from the inner loop */
438 /* When all recursions from this node down, are over, and all
439 dependencies have been added in proper order in the ordered array, add
440 also the package pkg to ordered array */
441 pkg_vec_insert(ordered, pkg);
447 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
449 pkg_vec_t *all, *ordered, *visited;
455 opkg_message(conf, OPKG_INFO,
456 "Configuring unpacked packages\n");
459 all = pkg_vec_alloc();
461 pkg_hash_fetch_available(&conf->pkg_hash, all);
463 /* Reorder pkgs in order to be configured according to the Depends: tag
465 opkg_message(conf, OPKG_INFO,
466 "Reordering packages before configuring them...\n");
467 ordered = pkg_vec_alloc();
468 visited = pkg_vec_alloc();
469 for(i = 0; i < all->len; i++) {
471 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
474 ic = opkg_prep_intercepts (conf);
480 for(i = 0; i < all->len; i++) {
483 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
486 if (pkg->state_status == SS_UNPACKED) {
487 opkg_message(conf, OPKG_NOTICE,
488 "Configuring %s\n", pkg->name);
490 r = opkg_configure(conf, pkg);
492 pkg->state_status = SS_INSTALLED;
493 pkg->parent->state_status = SS_INSTALLED;
494 pkg->state_flag &= ~SF_PREFER;
502 r = opkg_finalize_intercepts (ic);
508 pkg_vec_free(ordered);
509 pkg_vec_free(visited);
514 static opkg_conf_t *global_conf;
516 static void sigint_handler(int sig)
518 signal(sig, SIG_DFL);
519 opkg_message(NULL, OPKG_NOTICE,
520 "opkg: interrupted. writing out status database\n");
521 write_status_files_if_changed(global_conf);
525 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
532 signal(SIGINT, sigint_handler);
535 * Now scan through package names and install
537 for (i=0; i < argc; i++) {
540 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
541 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
542 if (err != EINVAL && err != 0)
545 pkg_info_preinstall_check(conf);
547 for (i=0; i < argc; i++) {
549 err = opkg_install_by_name(conf, arg);
550 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
551 opkg_message(conf, OPKG_ERROR,
552 "Cannot find package %s.\n",
557 opkg_configure_packages(conf, NULL);
559 write_status_files_if_changed(conf);
564 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
571 signal(SIGINT, sigint_handler);
574 for (i=0; i < argc; i++) {
577 err = opkg_prepare_url_for_install(conf, arg, &arg);
578 if (err != EINVAL && err != 0)
581 pkg_info_preinstall_check(conf);
583 for (i=0; i < argc; i++) {
585 if (conf->restrict_to_default_dest) {
586 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
590 opkg_message(conf, OPKG_NOTICE,
591 "Package %s not installed in %s\n",
592 argv[i], conf->default_dest->name);
596 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
600 opkg_upgrade_pkg(conf, pkg);
602 opkg_install_by_name(conf, arg);
606 pkg_vec_t *installed = pkg_vec_alloc();
608 pkg_info_preinstall_check(conf);
610 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
611 for (i = 0; i < installed->len; i++) {
612 pkg = installed->pkgs[i];
613 opkg_upgrade_pkg(conf, pkg);
615 pkg_vec_free(installed);
618 opkg_configure_packages(conf, NULL);
620 write_status_files_if_changed(conf);
625 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
631 pkg_info_preinstall_check(conf);
632 for (i = 0; i < argc; i++) {
635 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
637 opkg_message(conf, OPKG_ERROR,
638 "Cannot find package %s.\n"
639 "Check the spelling or perhaps run 'opkg update'\n",
644 err = opkg_download_pkg(conf, pkg, ".");
647 opkg_message(conf, OPKG_ERROR,
648 "Failed to download %s\n", pkg->name);
650 opkg_message(conf, OPKG_NOTICE,
651 "Downloaded %s as %s\n",
652 pkg->name, pkg->local_filename);
660 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
663 pkg_vec_t *available;
665 char *pkg_name = NULL;
670 available = pkg_vec_alloc();
671 pkg_hash_fetch_available(&conf->pkg_hash, available);
672 pkg_vec_sort(available, pkg_compare_names);
673 for (i=0; i < available->len; i++) {
674 pkg = available->pkgs[i];
675 /* if we have package name or pattern and pkg does not match, then skip it */
676 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
680 pkg_vec_free(available);
686 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
689 pkg_vec_t *available;
691 char *pkg_name = NULL;
696 available = pkg_vec_alloc();
697 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
698 pkg_vec_sort(available, pkg_compare_names);
699 for (i=0; i < available->len; i++) {
700 pkg = available->pkgs[i];
701 /* if we have package name or pattern and pkg does not match, then skip it */
702 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
707 pkg_vec_free(available);
712 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
714 struct active_list *head = prepare_upgrade_list(conf);
715 struct active_list *node=NULL;
716 pkg_t *_old_pkg, *_new_pkg;
718 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
719 _old_pkg = list_entry(node, pkg_t, list);
720 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
721 old_v = pkg_version_str_alloc(_old_pkg);
722 new_v = pkg_version_str_alloc(_new_pkg);
723 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
727 active_list_head_delete(head);
731 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
734 pkg_vec_t *available;
736 char *pkg_name = NULL;
742 available = pkg_vec_alloc();
744 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
746 pkg_hash_fetch_available(&conf->pkg_hash, available);
748 for (i=0; i < available->len; i++) {
749 pkg = available->pkgs[i];
750 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
754 pkg_formatted_info(stdout, pkg);
756 if (conf->verbosity >= OPKG_NOTICE) {
757 conffile_list_elt_t *iter;
758 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
759 conffile_t *cf = (conffile_t *)iter->data;
760 int modified = conffile_has_been_modified(conf, cf);
762 opkg_message(conf, OPKG_NOTICE,
763 "conffile=%s md5sum=%s modified=%d\n",
764 cf->name, cf->value, modified);
768 pkg_vec_free(available);
773 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
775 return opkg_info_status_cmd(conf, argc, argv, 0);
778 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
780 return opkg_info_status_cmd(conf, argc, argv, 1);
783 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
788 char *pkg_name = NULL;
792 err = opkg_configure_packages (conf, pkg_name);
795 err = opkg_configure_packages (conf, NULL);
798 write_status_files_if_changed(conf);
803 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
807 pkg_t *pkg_to_remove;
808 pkg_vec_t *available;
813 signal(SIGINT, sigint_handler);
815 pkg_info_preinstall_check(conf);
817 available = pkg_vec_alloc();
818 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
820 for (i=0; i<argc; i++) {
821 for (a=0; a<available->len; a++) {
822 pkg = available->pkgs[a];
823 if (fnmatch(argv[i], pkg->name, 0)) {
826 if (conf->restrict_to_default_dest) {
827 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
831 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
834 if (pkg_to_remove == NULL) {
835 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
838 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
839 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
842 opkg_remove_pkg(conf, pkg_to_remove, 0);
847 pkg_vec_free(available);
850 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
852 write_status_files_if_changed(conf);
856 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
860 const char *flags = argv[0];
863 signal(SIGINT, sigint_handler);
865 for (i=1; i < argc; i++) {
866 if (conf->restrict_to_default_dest) {
867 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
871 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
875 opkg_message(conf, OPKG_ERROR,
876 "Package %s is not installed.\n", argv[i]);
879 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
880 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
881 pkg->state_flag = pkg_state_flag_from_str(flags);
885 * Useful if a package is installed in an offline_root, and
886 * should be configured by opkg-cl configure at a later date.
888 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
889 pkg->state_status = pkg_state_status_from_str(flags);
892 opkg_state_changed++;
893 opkg_message(conf, OPKG_NOTICE,
894 "Setting flags for package %s to %s\n",
898 write_status_files_if_changed(conf);
902 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
906 str_list_elt_t *iter;
913 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
916 opkg_message(conf, OPKG_ERROR,
917 "Package %s not installed.\n", argv[0]);
921 files = pkg_get_installed_files(conf, pkg);
922 pkg_version = pkg_version_str_alloc(pkg);
924 printf("Package %s (%s) is installed on %s and has the following files:\n",
925 pkg->name, pkg_version, pkg->dest->name);
927 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
928 printf("%s\n", (char *)iter->data);
931 pkg_free_installed_files(pkg);
936 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
940 pkg_vec_t *available_pkgs;
941 compound_depend_t *cdep;
945 pkg_info_preinstall_check(conf);
947 available_pkgs = pkg_vec_alloc();
949 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
951 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
953 for (i=0; i<argc; i++) {
954 for (j=0; j<available_pkgs->len; j++) {
955 pkg = available_pkgs->pkgs[j];
957 if (fnmatch(argv[i], pkg->name, 0) != 0)
960 depends_count = pkg->depends_count +
961 pkg->pre_depends_count +
962 pkg->recommends_count +
965 opkg_message(conf, OPKG_NOTICE, "%s depends on:\n",
968 for (k=0; k<depends_count; k++) {
969 cdep = &pkg->depends[k];
971 if (cdep->type != DEPEND)
974 str = pkg_depend_str(pkg, k);
975 opkg_message(conf, OPKG_NOTICE, "\t%s\n", str);
982 pkg_vec_free(available_pkgs);
986 enum what_field_type {
995 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum depend_type what_field_type, int recursive, int argc, char **argv)
997 depend_t *possibility;
998 compound_depend_t *cdep;
999 pkg_vec_t *available_pkgs;
1003 const char *rel_str = NULL;
1006 switch (what_field_type) {
1007 case DEPEND: rel_str = "depends on"; break;
1008 case CONFLICTS: rel_str = "conflicts with"; break;
1009 case SUGGEST: rel_str = "suggests"; break;
1010 case RECOMMEND: rel_str = "recommends"; break;
1014 available_pkgs = pkg_vec_alloc();
1016 if (conf->query_all)
1017 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1019 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1021 /* mark the root set */
1022 pkg_vec_clear_marks(available_pkgs);
1023 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1024 for (i = 0; i < argc; i++)
1025 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
1027 for (i = 0; i < available_pkgs->len; i++) {
1028 pkg = available_pkgs->pkgs[i];
1029 if (pkg->state_flag & SF_MARKED) {
1030 /* mark the parent (abstract) package */
1031 pkg_mark_provides(pkg);
1032 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1036 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1040 for (j=0; j<available_pkgs->len; j++) {
1042 pkg = available_pkgs->pkgs[j];
1043 count = ((what_field_type == CONFLICTS)
1044 ? pkg->conflicts_count
1045 : pkg->pre_depends_count +
1046 pkg->depends_count +
1047 pkg->recommends_count +
1048 pkg->suggests_count);
1050 /* skip this package if it is already marked */
1051 if (pkg->parent->state_flag & SF_MARKED)
1054 for (k=0; k<count; k++) {
1055 cdep = (what_field_type == CONFLICTS)
1056 ? &pkg->conflicts[k]
1059 if (what_field_type != cdep->type)
1062 for (l=0; l<cdep->possibility_count; l++) {
1063 possibility = cdep->possibilities[l];
1065 if ((possibility->pkg->state_flag
1070 /* mark the depending package so we
1071 * won't visit it again */
1072 pkg->state_flag |= SF_MARKED;
1073 pkg_mark_provides(pkg);
1076 ver = pkg_version_str_alloc(pkg);
1077 opkg_message(conf, OPKG_NOTICE,
1082 possibility->pkg->name);
1084 if (possibility->version) {
1085 opkg_message(conf, OPKG_NOTICE,
1087 constraint_to_str(possibility->constraint),
1088 possibility->version);
1090 if (!pkg_dependence_satisfiable(conf, possibility))
1091 opkg_message(conf, OPKG_NOTICE,
1093 opkg_message(conf, OPKG_NOTICE, "\n");
1100 } while (changed && recursive);
1102 pkg_vec_free(available_pkgs);
1107 static int pkg_mark_provides(pkg_t *pkg)
1109 int provides_count = pkg->provides_count;
1110 abstract_pkg_t **provides = pkg->provides;
1112 pkg->parent->state_flag |= SF_MARKED;
1113 for (i = 0; i < provides_count; i++) {
1114 provides[i]->state_flag |= SF_MARKED;
1119 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1121 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 1, argc, argv);
1123 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1125 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 0, argc, argv);
1128 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1130 return opkg_what_depends_conflicts_cmd(conf, SUGGEST, 0, argc, argv);
1133 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1135 return opkg_what_depends_conflicts_cmd(conf, RECOMMEND, 0, argc, argv);
1138 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1140 return opkg_what_depends_conflicts_cmd(conf, CONFLICTS, 0, argc, argv);
1143 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1147 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1148 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1151 pkg_info_preinstall_check(conf);
1153 if (conf->query_all)
1154 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1156 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1157 for (i = 0; i < argc; i++) {
1158 const char *target = argv[i];
1161 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1163 for (j = 0; j < available_pkgs->len; j++) {
1164 pkg_t *pkg = available_pkgs->pkgs[j];
1166 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1167 for (k = 0; k < count; k++) {
1168 abstract_pkg_t *apkg =
1169 ((what_field_type == WHATPROVIDES)
1171 : pkg->replaces[k]);
1172 if (fnmatch(target, apkg->name, 0) == 0) {
1173 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1174 if (strcmp(target, apkg->name) != 0)
1175 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1176 opkg_message(conf, OPKG_ERROR, "\n");
1181 pkg_vec_free(available_pkgs);
1186 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1188 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1191 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1193 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1196 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1200 pkg_vec_t *installed;
1202 str_list_t *installed_files;
1203 str_list_elt_t *iter;
1204 char *installed_file;
1210 installed = pkg_vec_alloc();
1211 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1212 pkg_vec_sort(installed, pkg_compare_names);
1214 for (i=0; i < installed->len; i++) {
1215 pkg = installed->pkgs[i];
1217 installed_files = pkg_get_installed_files(conf, pkg);
1219 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1220 installed_file = (char *)iter->data;
1221 if (fnmatch(argv[0], installed_file, 0)==0)
1225 pkg_free_installed_files(pkg);
1228 pkg_vec_free(installed);
1233 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1236 /* this is a bit gross */
1238 parse_version(&p1, argv[0]);
1239 parse_version(&p2, argv[2]);
1240 return pkg_version_satisfied(&p1, &p2, argv[1]);
1242 opkg_message(conf, OPKG_ERROR,
1243 "opkg compare_versions <v1> <op> <v2>\n"
1244 "<op> is one of <= >= << >> =\n");
1249 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1251 nv_pair_list_elt_t *l;
1253 list_for_each_entry(l, &conf->arch_list.head, node) {
1254 nv_pair_t *nv = (nv_pair_t *)l->data;
1255 printf("arch %s %s\n", nv->name, nv->value);