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);
883 /* pb_ asked this feature 03292004 */
884 /* Actually I will use only this two, but this is an open for various status */
885 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
886 pkg->state_status = pkg_state_status_from_str(flags);
888 opkg_state_changed++;
889 opkg_message(conf, OPKG_NOTICE,
890 "Setting flags for package %s to %s\n",
894 write_status_files_if_changed(conf);
898 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
902 str_list_elt_t *iter;
909 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
912 opkg_message(conf, OPKG_ERROR,
913 "Package %s not installed.\n", argv[0]);
917 files = pkg_get_installed_files(conf, pkg);
918 pkg_version = pkg_version_str_alloc(pkg);
920 printf("Package %s (%s) is installed on %s and has the following files:\n",
921 pkg->name, pkg_version, pkg->dest->name);
923 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
924 printf("%s\n", (char *)iter->data);
927 pkg_free_installed_files(pkg);
932 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
936 pkg_vec_t *available_pkgs = pkg_vec_alloc();
937 const char *rel_str = "depends on";
940 pkg_info_preinstall_check(conf);
943 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
945 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
946 for (i = 0; i < argc; i++) {
947 const char *target = argv[i];
950 opkg_message(conf, OPKG_NOTICE, "target=%s\n", target);
952 for (j = 0; j < available_pkgs->len; j++) {
953 pkg_t *pkg = available_pkgs->pkgs[j];
954 if (fnmatch(target, pkg->name, 0) == 0) {
956 int count = pkg->depends_count + pkg->pre_depends_count;
957 opkg_message(conf, OPKG_NOTICE, "What %s (arch=%s) %s\n",
958 target, pkg->architecture, rel_str);
959 for (k = 0; k < count; k++) {
960 compound_depend_t *cdepend = &pkg->depends[k];
962 for (l = 0; l < cdepend->possibility_count; l++) {
963 depend_t *possibility = cdepend->possibilities[l];
964 opkg_message(conf, OPKG_NOTICE, " %s", possibility->pkg->name);
965 if (conf->verbosity >= OPKG_NOTICE) {
966 if (possibility->version) {
967 char *typestr = NULL;
968 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
969 switch (possibility->constraint) {
970 case NONE: typestr = "none"; break;
971 case EARLIER: typestr = "<"; break;
972 case EARLIER_EQUAL: typestr = "<="; break;
973 case EQUAL: typestr = "="; break;
974 case LATER_EQUAL: typestr = ">="; break;
975 case LATER: typestr = ">"; break;
977 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
980 opkg_message(conf, OPKG_NOTICE, "\n");
986 pkg_vec_free(available_pkgs);
991 enum what_field_type {
1000 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum depend_type what_field_type, int recursive, int argc, char **argv)
1004 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1005 const char *rel_str = NULL;
1009 switch (what_field_type) {
1010 case DEPEND: rel_str = "depends on"; break;
1011 case CONFLICTS: rel_str = "conflicts with"; break;
1012 case SUGGEST: rel_str = "suggests"; break;
1013 case RECOMMEND: rel_str = "recommends"; break;
1017 if (conf->query_all)
1018 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1020 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1022 /* mark the root set */
1023 pkg_vec_clear_marks(available_pkgs);
1024 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1025 for (i = 0; i < argc; i++) {
1026 const char *dependee_pattern = argv[i];
1027 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1029 for (i = 0; i < available_pkgs->len; i++) {
1030 pkg_t *pkg = available_pkgs->pkgs[i];
1031 if (pkg->state_flag & SF_MARKED) {
1032 /* mark the parent (abstract) package */
1033 pkg_mark_provides(pkg);
1034 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1038 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1043 for (j = 0; j < available_pkgs->len; j++) {
1044 pkg_t *pkg = available_pkgs->pkgs[j];
1046 int count = ((what_field_type == CONFLICTS)
1047 ? pkg->conflicts_count
1048 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + 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 compound_depend_t *cdepend =
1055 (what_field_type == CONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1057 if (what_field_type != cdepend->type)
1059 for (l = 0; l < cdepend->possibility_count; l++) {
1060 depend_t *possibility = cdepend->possibilities[l];
1061 if (possibility->pkg->state_flag & SF_MARKED) {
1062 /* mark the depending package so we won't visit it again */
1063 pkg->state_flag |= SF_MARKED;
1064 pkg_mark_provides(pkg);
1067 if (conf->verbosity >= OPKG_NOTICE) {
1068 char *ver = pkg_version_str_alloc(pkg);
1069 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1070 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1071 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1072 if (possibility->version) {
1073 char *typestr = NULL;
1074 switch (possibility->constraint) {
1075 case NONE: typestr = "none"; break;
1076 case EARLIER: typestr = "<"; break;
1077 case EARLIER_EQUAL: typestr = "<="; break;
1078 case EQUAL: typestr = "="; break;
1079 case LATER_EQUAL: typestr = ">="; break;
1080 case LATER: typestr = ">"; break;
1082 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1085 if (!pkg_dependence_satisfiable(conf, possibility))
1086 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1088 opkg_message(conf, OPKG_NOTICE, "\n");
1096 } while (changed && recursive);
1097 pkg_vec_free(available_pkgs);
1103 static int pkg_mark_provides(pkg_t *pkg)
1105 int provides_count = pkg->provides_count;
1106 abstract_pkg_t **provides = pkg->provides;
1108 pkg->parent->state_flag |= SF_MARKED;
1109 for (i = 0; i < provides_count; i++) {
1110 provides[i]->state_flag |= SF_MARKED;
1115 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1117 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 1, argc, argv);
1119 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1121 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 0, argc, argv);
1124 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1126 return opkg_what_depends_conflicts_cmd(conf, SUGGEST, 0, argc, argv);
1129 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1131 return opkg_what_depends_conflicts_cmd(conf, RECOMMEND, 0, argc, argv);
1134 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1136 return opkg_what_depends_conflicts_cmd(conf, CONFLICTS, 0, argc, argv);
1139 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1143 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1144 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1147 pkg_info_preinstall_check(conf);
1149 if (conf->query_all)
1150 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1152 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1153 for (i = 0; i < argc; i++) {
1154 const char *target = argv[i];
1157 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1159 for (j = 0; j < available_pkgs->len; j++) {
1160 pkg_t *pkg = available_pkgs->pkgs[j];
1162 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1163 for (k = 0; k < count; k++) {
1164 abstract_pkg_t *apkg =
1165 ((what_field_type == WHATPROVIDES)
1167 : pkg->replaces[k]);
1168 if (fnmatch(target, apkg->name, 0) == 0) {
1169 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1170 if (strcmp(target, apkg->name) != 0)
1171 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1172 opkg_message(conf, OPKG_ERROR, "\n");
1177 pkg_vec_free(available_pkgs);
1182 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1184 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1187 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1189 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1192 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1196 pkg_vec_t *installed;
1198 str_list_t *installed_files;
1199 str_list_elt_t *iter;
1200 char *installed_file;
1206 installed = pkg_vec_alloc();
1207 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1208 pkg_vec_sort(installed, pkg_compare_names);
1210 for (i=0; i < installed->len; i++) {
1211 pkg = installed->pkgs[i];
1213 installed_files = pkg_get_installed_files(conf, pkg);
1215 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1216 installed_file = (char *)iter->data;
1217 if (fnmatch(argv[0], installed_file, 0)==0)
1221 pkg_free_installed_files(pkg);
1224 pkg_vec_free(installed);
1229 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1232 /* this is a bit gross */
1234 parse_version(&p1, argv[0]);
1235 parse_version(&p2, argv[2]);
1236 return pkg_version_satisfied(&p1, &p2, argv[1]);
1238 opkg_message(conf, OPKG_ERROR,
1239 "opkg compare_versions <v1> <op> <v2>\n"
1240 "<op> is one of <= >= << >> =\n");
1245 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1247 nv_pair_list_elt_t *l;
1249 list_for_each_entry(l, &conf->arch_list.head, node) {
1250 nv_pair_t *nv = (nv_pair_t *)l->data;
1251 printf("arch %s %s\n", nv->name, nv->value);