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.
27 #include "opkg_conf.h"
29 #include "opkg_message.h"
32 #include "pkg_parse.h"
33 #include "sprintf_alloc.h"
35 #include "file_util.h"
36 #include "libbb/libbb.h"
37 #include "opkg_utils.h"
38 #include "opkg_defines.h"
39 #include "opkg_download.h"
40 #include "opkg_install.h"
41 #include "opkg_upgrade.h"
42 #include "opkg_remove.h"
43 #include "opkg_configure.h"
46 static void print_pkg(pkg_t * pkg)
48 char *version = pkg_version_str_alloc(pkg);
49 char *description = pkg_get_string(pkg, PKG_DESCRIPTION);
50 printf("%s - %s", pkg->name, version);
52 printf(" - %lu", (unsigned long) pkg_get_int(pkg, PKG_SIZE));
54 printf(" - %s", description);
59 int opkg_state_changed;
61 static void write_status_files_if_changed(void)
63 if (opkg_state_changed && !conf->noaction) {
64 opkg_msg(INFO, "Writing status file.\n");
65 opkg_conf_write_status_files();
66 pkg_write_changed_filelists();
68 opkg_msg(DEBUG, "Nothing to be done.\n");
72 static void sigint_handler(int sig)
75 opkg_msg(NOTICE, "Interrupted. Writing out status database.\n");
76 write_status_files_if_changed();
80 static int opkg_update_cmd(int argc, char **argv)
87 pkg_src_list_elt_t *iter;
90 sprintf_alloc(&lists_dir, "%s",
91 conf->restrict_to_default_dest ? conf->default_dest->
92 lists_dir : conf->lists_dir);
94 if (!file_is_dir(lists_dir)) {
95 if (file_exists(lists_dir)) {
96 opkg_msg(ERROR, "%s exists, but is not a directory.\n",
101 err = file_mkdir_hier(lists_dir, 0755);
110 sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
111 if (mkdtemp(tmp) == NULL) {
112 opkg_perror(ERROR, "Failed to make temp dir %s", conf->tmp_dir);
116 for (iter = void_list_first(&conf->pkg_src_list); iter;
117 iter = void_list_next(&conf->pkg_src_list, iter)) {
118 char *url, *list_file_name;
120 src = (pkg_src_t *) iter->data;
122 if (src->extra_data && strcmp(src->extra_data, "__dummy__ "))
125 if (src->extra_data) /* debian style? */
126 sprintf_alloc(&url, "%s/%s/%s", src->value,
128 src->gzip ? "Packages.gz" : "Packages");
130 sprintf_alloc(&url, "%s/%s", src->value,
131 src->gzip ? "Packages.gz" : "Packages");
133 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
134 pkglist_dl_error = 0;
135 if (opkg_download(url, list_file_name, NULL, NULL, 0)) {
137 pkglist_dl_error = 1;
139 "*** Failed to download the package list from %s\n\n",
143 "Updated list of available packages in %s\n",
147 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN)
148 if (pkglist_dl_error == 0 && conf->check_signature) {
149 /* download detached signitures to verify the package lists */
150 /* get the url for the sig file */
151 if (src->extra_data) /* debian style? */
152 sprintf_alloc(&url, "%s/%s/%s", src->value,
153 src->extra_data, "Packages.sig");
155 sprintf_alloc(&url, "%s/%s", src->value,
158 /* create temporary file for it */
161 /* Put the signature in the right place */
162 sprintf_alloc(&tmp_file_name, "%s/%s.sig", lists_dir,
165 err = opkg_download(url, tmp_file_name, NULL, NULL, 0);
169 "Signature file download failed.\n");
172 opkg_verify_file(list_file_name,
176 "Signature check passed.\n");
179 "Signature check failed.\n");
181 if (err && !conf->force_signature) {
182 /* The signature was wrong so delete it */
184 "Remove wrong Signature file.\n");
185 unlink(tmp_file_name);
186 unlink(list_file_name);
188 /* We shouldn't unlink the signature ! */
189 // unlink (tmp_file_name);
196 free(list_file_name);
205 struct opkg_intercept {
210 typedef struct opkg_intercept *opkg_intercept_t;
212 static opkg_intercept_t opkg_prep_intercepts(void)
214 opkg_intercept_t ctx;
217 ctx = xcalloc(1, sizeof(*ctx));
218 ctx->oldpath = xstrdup(getenv("PATH"));
219 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
220 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX",
223 if (mkdtemp(ctx->statedir) == NULL) {
224 opkg_perror(ERROR, "Failed to make temp dir %s", ctx->statedir);
232 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
233 setenv("PATH", newpath, 1);
239 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
244 setenv("PATH", ctx->oldpath, 1);
247 dir = opendir(ctx->statedir);
250 while (de = readdir(dir), de != NULL) {
253 if (de->d_name[0] == '.')
256 sprintf_alloc(&path, "%s/%s", ctx->statedir,
258 if (access(path, X_OK) == 0) {
259 const char *argv[] = { "sh", "-c", path, NULL };
266 opkg_perror(ERROR, "Failed to open dir %s", ctx->statedir);
275 /* For package pkg do the following: If it is already visited, return. If not,
276 add it in visited list and recurse to its deps. Finally, add it to ordered
278 pkg_vec all contains all available packages in repos.
279 pkg_vec visited contains packages already visited by this function, and is
280 used to end recursion and avoid an infinite loop on graph cycles.
281 pkg_vec ordered will finally contain the ordered set of packages.
284 opkg_recurse_pkgs_in_order(pkg_t * pkg, pkg_vec_t * all,
285 pkg_vec_t * visited, pkg_vec_t * ordered)
289 compound_depend_t *compound_depend;
290 depend_t **possible_satisfiers;
291 abstract_pkg_t *abpkg;
292 abstract_pkg_t **dependents;
294 /* If it's just an available package, that is, not installed and not even
296 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
297 would do here. However, if there is an intermediate node (pkg) that is
298 configured and installed between two unpacked packages, the latter
299 won't be properly reordered, unless all installed/unpacked pkgs are
301 if (pkg->state_status == SS_NOT_INSTALLED)
304 /* If the package has already been visited (by this function), skip it */
305 for (j = 0; j < visited->len; j++)
306 if (!strcmp(visited->pkgs[j]->name, pkg->name)) {
307 opkg_msg(DEBUG, "pkg %s already visited, skipping.\n",
312 pkg_vec_insert(visited, pkg);
314 opkg_msg(DEBUG, "pkg %s.\n", pkg->name);
316 /* Iterate over all the dependencies of pkg. For each one, find a package
317 that is either installed or unpacked and satisfies this dependency.
318 (there should only be one such package per dependency installed or
319 unpacked). Then recurse to the dependency package */
320 for (compound_depend = pkg_get_ptr(pkg, PKG_DEPENDS); compound_depend && compound_depend->type; compound_depend++) {
321 possible_satisfiers = compound_depend->possibilities;
322 for (k = 0; k < compound_depend->possibility_count; k++) {
323 abpkg = possible_satisfiers[k]->pkg;
324 dependents = abpkg->provided_by->pkgs;
326 if (dependents != NULL)
327 while (l < abpkg->provided_by->len
328 && dependents[l] != NULL) {
330 "Descending on pkg %s.\n",
331 dependents[l]->name);
333 /* find whether dependent l is installed or unpacked,
334 * and then find which package in the list satisfies it */
335 for (m = 0; m < all->len; m++) {
337 if (dep->state_status !=
343 opkg_recurse_pkgs_in_order
347 /* Stop the outer loop */
351 /* break from the inner loop */
360 /* When all recursions from this node down, are over, and all
361 dependencies have been added in proper order in the ordered array, add
362 also the package pkg to ordered array */
363 pkg_vec_insert(ordered, pkg);
369 static int opkg_configure_packages(char *pkg_name)
371 pkg_vec_t *all, *ordered, *visited;
377 opkg_msg(INFO, "Configuring unpacked packages.\n");
379 all = pkg_vec_alloc();
381 pkg_hash_fetch_available(all);
383 /* Reorder pkgs in order to be configured according to the Depends: tag
385 opkg_msg(INFO, "Reordering packages before configuring them...\n");
386 ordered = pkg_vec_alloc();
387 visited = pkg_vec_alloc();
388 for (i = 0; i < all->len; i++) {
390 opkg_recurse_pkgs_in_order(pkg, all, visited, ordered);
393 ic = opkg_prep_intercepts();
399 for (i = 0; i < ordered->len; i++) {
400 pkg = ordered->pkgs[i];
402 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
405 if (pkg->state_status == SS_UNPACKED) {
406 opkg_msg(NOTICE, "Configuring %s.\n", pkg->name);
407 r = opkg_configure(pkg);
409 pkg->state_status = SS_INSTALLED;
410 pkg->parent->state_status = SS_INSTALLED;
411 pkg->state_flag &= ~SF_PREFER;
412 opkg_state_changed++;
419 if (opkg_finalize_intercepts(ic))
424 pkg_vec_free(ordered);
425 pkg_vec_free(visited);
430 static int opkg_remove_cmd(int argc, char **argv);
432 static int opkg_install_cmd(int argc, char **argv)
438 if (conf->force_reinstall) {
439 int saved_force_depends = conf->force_depends;
440 conf->force_depends = 1;
441 (void)opkg_remove_cmd(argc, argv);
442 conf->force_depends = saved_force_depends;
443 conf->force_reinstall = 0;
446 signal(SIGINT, sigint_handler);
449 * Now scan through package names and install
451 for (i = 0; i < argc; i++) {
454 opkg_msg(DEBUG2, "%s\n", arg);
455 if (opkg_prepare_url_for_install(arg, &argv[i]))
458 pkg_info_preinstall_check();
460 for (i = 0; i < argc; i++) {
462 if (opkg_install_by_name(arg)) {
463 opkg_msg(ERROR, "Cannot install package %s.\n", arg);
468 if (opkg_configure_packages(NULL))
471 write_status_files_if_changed();
476 static int opkg_upgrade_cmd(int argc, char **argv)
482 signal(SIGINT, sigint_handler);
485 for (i = 0; i < argc; i++) {
488 if (opkg_prepare_url_for_install(arg, &arg))
491 pkg_info_preinstall_check();
493 for (i = 0; i < argc; i++) {
495 if (conf->restrict_to_default_dest) {
497 pkg_hash_fetch_installed_by_name_dest(argv
503 "Package %s not installed in %s.\n",
505 conf->default_dest->name);
509 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
512 if (opkg_upgrade_pkg(pkg))
515 if (opkg_install_by_name(arg))
521 if (opkg_configure_packages(NULL))
524 write_status_files_if_changed();
529 static int opkg_download_cmd(int argc, char **argv)
535 pkg_info_preinstall_check();
536 for (i = 0; i < argc; i++) {
539 pkg = pkg_hash_fetch_best_installation_candidate_by_name(arg);
541 opkg_msg(ERROR, "Cannot find package %s.\n", arg);
545 if (opkg_download_pkg(pkg, "."))
549 opkg_msg(ERROR, "Failed to download %s.\n", pkg->name);
551 opkg_msg(NOTICE, "Downloaded %s as %s.\n",
552 pkg->name, pkg_get_string(pkg, PKG_LOCAL_FILENAME));
559 static int opkg_list_find_cmd(int argc, char **argv, int use_desc)
562 pkg_vec_t *available;
564 char *pkg_name = NULL;
570 available = pkg_vec_alloc();
571 pkg_hash_fetch_available(available);
572 pkg_vec_sort(available, pkg_compare_names);
573 for (i = 0; i < available->len; i++) {
574 pkg = available->pkgs[i];
575 description = use_desc ? pkg_get_string(pkg, PKG_DESCRIPTION) : NULL;
576 /* if we have package name or pattern and pkg does not match, then skip it */
577 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase) &&
578 (!use_desc || !description
579 || fnmatch(pkg_name, description, conf->nocase)))
583 pkg_vec_free(available);
588 static int opkg_list_cmd(int argc, char **argv)
590 return opkg_list_find_cmd(argc, argv, 0);
593 static int opkg_find_cmd(int argc, char **argv)
595 return opkg_list_find_cmd(argc, argv, 1);
598 static int opkg_list_installed_cmd(int argc, char **argv)
601 pkg_vec_t *available;
603 char *pkg_name = NULL;
608 available = pkg_vec_alloc();
609 pkg_hash_fetch_all_installed(available);
610 pkg_vec_sort(available, pkg_compare_names);
611 for (i = 0; i < available->len; i++) {
612 pkg = available->pkgs[i];
613 /* if we have package name or pattern and pkg does not match, then skip it */
614 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
619 pkg_vec_free(available);
624 static int opkg_list_changed_conffiles_cmd(int argc, char **argv)
627 pkg_vec_t *available;
629 char *pkg_name = NULL;
630 conffile_list_elt_t *iter;
637 available = pkg_vec_alloc();
638 pkg_hash_fetch_all_installed(available);
639 pkg_vec_sort(available, pkg_compare_names);
640 for (i = 0; i < available->len; i++) {
641 pkg = available->pkgs[i];
642 cl = pkg_get_ptr(pkg, PKG_CONFFILES);
643 /* if we have package name or pattern and pkg does not match, then skip it */
644 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
646 if (!cl || nv_pair_list_empty(cl))
648 for (iter = nv_pair_list_first(cl); iter;
649 iter = nv_pair_list_next(cl, iter)) {
650 cf = (conffile_t *) iter->data;
651 if (cf->name && cf->value
652 && conffile_has_been_modified(cf))
653 printf("%s\n", cf->name);
656 pkg_vec_free(available);
660 static int opkg_list_upgradable_cmd(int argc, char **argv)
662 struct active_list *head = prepare_upgrade_list();
663 struct active_list *node = NULL;
664 pkg_t *_old_pkg, *_new_pkg;
666 for (node = active_list_next(head, head); node;
667 node = active_list_next(head, node)) {
668 _old_pkg = node->pkg;
670 pkg_hash_fetch_best_installation_candidate_by_name
672 if (_new_pkg == NULL)
674 old_v = pkg_version_str_alloc(_old_pkg);
675 new_v = pkg_version_str_alloc(_new_pkg);
676 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
680 active_list_head_delete(head);
684 static int opkg_info_status_cmd(int argc, char **argv, int installed_only)
687 pkg_vec_t *available;
689 char *pkg_name = NULL;
696 available = pkg_vec_alloc();
698 pkg_hash_fetch_all_installed(available);
700 pkg_hash_fetch_available(available);
702 for (i = 0; i < available->len; i++) {
703 pkg = available->pkgs[i];
704 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) {
708 pkg_formatted_info(stdout, pkg);
710 cl = pkg_get_ptr(pkg, PKG_CONFFILES);
712 if (conf->verbosity >= NOTICE && cl) {
713 conffile_list_elt_t *iter;
714 for (iter = nv_pair_list_first(cl); iter;
715 iter = nv_pair_list_next(cl, iter)) {
716 conffile_t *cf = (conffile_t *) iter->data;
717 int modified = conffile_has_been_modified(cf);
720 "conffile=%s md5sum=%s modified=%d.\n",
721 cf->name, cf->value, modified);
725 pkg_vec_free(available);
730 static int opkg_info_cmd(int argc, char **argv)
732 return opkg_info_status_cmd(argc, argv, 0);
735 static int opkg_status_cmd(int argc, char **argv)
737 return opkg_info_status_cmd(argc, argv, 1);
740 static int opkg_configure_cmd(int argc, char **argv)
743 char *pkg_name = NULL;
748 err = opkg_configure_packages(pkg_name);
750 write_status_files_if_changed();
755 static int opkg_remove_cmd(int argc, char **argv)
757 int i, a, done, err = 0;
759 pkg_t *pkg_to_remove;
760 pkg_vec_t *available;
764 signal(SIGINT, sigint_handler);
766 pkg_info_preinstall_check();
768 available = pkg_vec_alloc();
769 pkg_hash_fetch_all_installed(available);
771 for (i = 0; i < argc; i++) {
772 for (a = 0; a < available->len; a++) {
773 pkg = available->pkgs[a];
774 if (fnmatch(argv[i], pkg->name, conf->nocase)) {
777 if (conf->restrict_to_default_dest) {
779 pkg_hash_fetch_installed_by_name_dest(pkg->
785 pkg_hash_fetch_installed_by_name(pkg->name);
788 if (pkg_to_remove == NULL) {
790 "Package %s is not installed.\n",
794 if (pkg->state_status == SS_NOT_INSTALLED) {
795 opkg_msg(ERROR, "Package %s not installed.\n",
800 if (opkg_remove_pkg(pkg_to_remove, 0))
807 pkg_vec_free(available);
810 opkg_msg(NOTICE, "No packages removed.\n");
812 write_status_files_if_changed();
816 static int opkg_flag_cmd(int argc, char **argv)
820 const char *flags = argv[0];
822 signal(SIGINT, sigint_handler);
824 for (i = 1; i < argc; i++) {
825 if (conf->restrict_to_default_dest) {
826 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
830 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
834 opkg_msg(ERROR, "Package %s is not installed.\n",
838 if ((strcmp(flags, "hold") == 0)
839 || (strcmp(flags, "noprune") == 0)
840 || (strcmp(flags, "user") == 0)
841 || (strcmp(flags, "ok") == 0)) {
842 pkg->state_flag = pkg_state_flag_from_str(flags);
846 * Useful if a package is installed in an offline_root, and
847 * should be configured by opkg-cl configure at a later date.
849 if ((strcmp(flags, "installed") == 0)
850 || (strcmp(flags, "unpacked") == 0)) {
851 pkg->state_status = pkg_state_status_from_str(flags);
854 opkg_state_changed++;
855 opkg_msg(NOTICE, "Setting flags for package %s to %s.\n",
859 write_status_files_if_changed();
863 static int opkg_files_cmd(int argc, char **argv)
867 str_list_elt_t *iter;
874 pkg = pkg_hash_fetch_installed_by_name(argv[0]);
876 opkg_msg(ERROR, "Package %s not installed.\n", argv[0]);
880 files = pkg_get_installed_files(pkg);
881 pkg_version = pkg_version_str_alloc(pkg);
884 ("Package %s (%s) is installed on %s and has the following files:\n",
885 pkg->name, pkg_version, pkg->dest->name);
887 for (iter = str_list_first(files); iter;
888 iter = str_list_next(files, iter))
889 printf("%s\n", (char *)iter->data);
892 pkg_free_installed_files(pkg);
897 static int opkg_depends_cmd(int argc, char **argv)
900 pkg_vec_t *available_pkgs;
901 compound_depend_t *cdep;
905 pkg_info_preinstall_check();
907 available_pkgs = pkg_vec_alloc();
909 pkg_hash_fetch_available(available_pkgs);
911 pkg_hash_fetch_all_installed(available_pkgs);
913 for (i = 0; i < argc; i++) {
914 for (j = 0; j < available_pkgs->len; j++) {
915 pkg = available_pkgs->pkgs[j];
917 if (fnmatch(argv[i], pkg->name, conf->nocase) != 0)
920 opkg_msg(NOTICE, "%s depends on:\n", pkg->name);
922 for (k = 0, cdep = pkg_get_ptr(pkg, PKG_DEPENDS); cdep && cdep->type; k++, cdep++) {
923 if (cdep->type != DEPEND)
926 str = pkg_depend_str(pkg, k);
927 opkg_msg(NOTICE, "\t%s\n", str);
934 pkg_vec_free(available_pkgs);
938 static int pkg_mark_provides(pkg_t * pkg)
940 abstract_pkg_t **provider = pkg_get_ptr(pkg, PKG_PROVIDES);
942 pkg->parent->state_flag |= SF_MARKED;
944 while (provider && *provider) {
945 (*provider)->state_flag |= SF_MARKED;
952 enum what_field_type {
962 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive,
963 int argc, char **argv)
965 depend_t *possibility;
966 compound_depend_t *cdep, *deps;
967 pkg_vec_t *available_pkgs;
971 const char *rel_str = NULL;
974 switch (what_field_type) {
976 rel_str = "depends on";
979 rel_str = "conflicts with";
982 rel_str = "suggests";
985 rel_str = "recommends";
991 available_pkgs = pkg_vec_alloc();
994 pkg_hash_fetch_available(available_pkgs);
996 pkg_hash_fetch_all_installed(available_pkgs);
998 /* mark the root set */
999 pkg_vec_clear_marks(available_pkgs);
1000 opkg_msg(NOTICE, "Root set:\n");
1001 for (i = 0; i < argc; i++)
1002 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
1004 for (i = 0; i < available_pkgs->len; i++) {
1005 pkg = available_pkgs->pkgs[i];
1006 if (pkg->state_flag & SF_MARKED) {
1007 /* mark the parent (abstract) package */
1008 pkg_mark_provides(pkg);
1009 opkg_msg(NOTICE, " %s\n", pkg->name);
1013 opkg_msg(NOTICE, "What %s root set\n", rel_str);
1017 for (j = 0; j < available_pkgs->len; j++) {
1019 pkg = available_pkgs->pkgs[j];
1021 count = ((what_field_type == CONFLICTS)
1022 ? pkg->conflicts_count
1023 : pkg->pre_depends_count +
1024 pkg->depends_count +
1025 pkg->recommends_count + pkg->suggests_count);
1028 /* skip this package if it is already marked */
1029 if (pkg->parent->state_flag & SF_MARKED)
1032 deps = pkg_get_ptr(pkg, (what_field_type == CONFLICTS) ? PKG_CONFLICTS : PKG_DEPENDS);
1034 for (cdep = deps; cdep->type; cdep++) {
1035 if (what_field_type != cdep->type)
1038 for (l = 0; l < cdep->possibility_count; l++) {
1039 possibility = cdep->possibilities[l];
1041 if ((possibility->pkg->state_flag
1046 /* mark the depending package so we
1047 * won't visit it again */
1048 pkg->state_flag |= SF_MARKED;
1049 pkg_mark_provides(pkg);
1052 ver = pkg_version_str_alloc(pkg);
1053 opkg_msg(NOTICE, "\t%s %s\t%s %s",
1057 possibility->pkg->name);
1059 if (possibility->version) {
1060 opkg_msg(NOTICE, " (%s%s)",
1064 possibility->version);
1066 if (!pkg_dependence_satisfiable
1070 opkg_message(NOTICE, "\n");
1077 } while (changed && recursive);
1079 pkg_vec_free(available_pkgs);
1084 static int opkg_whatdepends_recursively_cmd(int argc, char **argv)
1086 return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv);
1089 static int opkg_whatdepends_cmd(int argc, char **argv)
1091 return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv);
1094 static int opkg_whatsuggests_cmd(int argc, char **argv)
1096 return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv);
1099 static int opkg_whatrecommends_cmd(int argc, char **argv)
1101 return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv);
1104 static int opkg_whatconflicts_cmd(int argc, char **argv)
1106 return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv);
1110 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc,
1113 abstract_pkg_t *apkg, **abpkgs;
1116 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1117 const char *rel_str =
1118 (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1121 pkg_info_preinstall_check();
1123 if (conf->query_all)
1124 pkg_hash_fetch_available(available_pkgs);
1126 pkg_hash_fetch_all_installed(available_pkgs);
1127 for (i = 0; i < argc; i++) {
1128 const char *target = argv[i];
1131 opkg_msg(NOTICE, "What %s %s\n", rel_str, target);
1132 for (j = 0; j < available_pkgs->len; j++) {
1133 pkg_t *pkg = available_pkgs->pkgs[j];
1134 abpkgs = pkg_get_ptr(pkg, (what_field_type == WHATPROVIDES) ? PKG_PROVIDES : PKG_REPLACES);
1136 while (abpkgs && *abpkgs) {
1139 if (fnmatch(target, apkg->name, conf->nocase))
1142 opkg_msg(NOTICE, " %s", pkg->name);
1144 if ((conf->nocase ? strcasecmp(target, apkg->name)
1145 : strcmp(target, apkg->name)))
1146 opkg_msg(NOTICE, "\t%s %s\n", rel_str, apkg->name);
1148 opkg_message(NOTICE, "\n");
1153 pkg_vec_free(available_pkgs);
1158 static int opkg_whatprovides_cmd(int argc, char **argv)
1160 return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv);
1163 static int opkg_whatreplaces_cmd(int argc, char **argv)
1165 return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv);
1168 static int opkg_search_cmd(int argc, char **argv)
1172 pkg_vec_t *installed;
1174 str_list_t *installed_files;
1175 str_list_elt_t *iter;
1176 char *installed_file;
1182 installed = pkg_vec_alloc();
1183 pkg_hash_fetch_all_installed(installed);
1184 pkg_vec_sort(installed, pkg_compare_names);
1186 for (i = 0; i < installed->len; i++) {
1187 pkg = installed->pkgs[i];
1189 installed_files = pkg_get_installed_files(pkg);
1191 for (iter = str_list_first(installed_files); iter;
1192 iter = str_list_next(installed_files, iter)) {
1193 installed_file = (char *)iter->data;
1194 if (fnmatch(argv[0], installed_file, conf->nocase) == 0)
1198 pkg_free_installed_files(pkg);
1201 pkg_vec_free(installed);
1206 static int opkg_compare_versions_cmd(int argc, char **argv)
1209 /* this is a bit gross */
1211 parse_version(&p1, argv[0]);
1212 parse_version(&p2, argv[2]);
1213 return pkg_version_satisfied(&p1, &p2, argv[1]);
1216 "opkg compare_versions <v1> <op> <v2>\n"
1217 "<op> is one of <= >= << >> =\n");
1222 static int opkg_print_architecture_cmd(int argc, char **argv)
1224 nv_pair_list_elt_t *l;
1226 list_for_each_entry(l, &conf->arch_list.head, node) {
1227 nv_pair_t *nv = (nv_pair_t *) l->data;
1228 printf("arch %s %s\n", nv->name, nv->value);
1233 /* XXX: CLEANUP: The usage strings should be incorporated into this
1234 array for easier maintenance */
1235 static opkg_cmd_t cmds[] = {
1236 {"update", 0, (opkg_cmd_fun_t) opkg_update_cmd,
1237 PFM_DESCRIPTION | PFM_SOURCE},
1238 {"upgrade", 1, (opkg_cmd_fun_t) opkg_upgrade_cmd,
1239 PFM_DESCRIPTION | PFM_SOURCE},
1240 {"list", 0, (opkg_cmd_fun_t) opkg_list_cmd, PFM_SOURCE},
1241 {"list_installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1243 {"list-installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1245 {"list_upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1247 {"list-upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1249 {"list_changed_conffiles", 0,
1250 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1251 {"list-changed-conffiles", 0,
1252 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1253 {"info", 0, (opkg_cmd_fun_t) opkg_info_cmd, 0},
1254 {"flag", 1, (opkg_cmd_fun_t) opkg_flag_cmd,
1255 PFM_DESCRIPTION | PFM_SOURCE},
1256 {"status", 0, (opkg_cmd_fun_t) opkg_status_cmd,
1257 PFM_DESCRIPTION | PFM_SOURCE},
1258 {"install", 1, (opkg_cmd_fun_t) opkg_install_cmd,
1259 PFM_DESCRIPTION | PFM_SOURCE},
1260 {"remove", 1, (opkg_cmd_fun_t) opkg_remove_cmd,
1261 PFM_DESCRIPTION | PFM_SOURCE},
1262 {"configure", 0, (opkg_cmd_fun_t) opkg_configure_cmd,
1263 PFM_DESCRIPTION | PFM_SOURCE},
1264 {"files", 1, (opkg_cmd_fun_t) opkg_files_cmd,
1265 PFM_DESCRIPTION | PFM_SOURCE},
1266 {"search", 1, (opkg_cmd_fun_t) opkg_search_cmd,
1267 PFM_DESCRIPTION | PFM_SOURCE},
1268 {"find", 1, (opkg_cmd_fun_t) opkg_find_cmd, PFM_SOURCE},
1269 {"download", 1, (opkg_cmd_fun_t) opkg_download_cmd,
1270 PFM_DESCRIPTION | PFM_SOURCE},
1271 {"compare_versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd,
1272 PFM_DESCRIPTION | PFM_SOURCE},
1273 {"compare-versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd,
1274 PFM_DESCRIPTION | PFM_SOURCE},
1275 {"print-architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1276 PFM_DESCRIPTION | PFM_SOURCE},
1277 {"print_architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1278 PFM_DESCRIPTION | PFM_SOURCE},
1279 {"print-installation-architecture", 0,
1280 (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1281 PFM_DESCRIPTION | PFM_SOURCE},
1282 {"print_installation_architecture", 0,
1283 (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1284 PFM_DESCRIPTION | PFM_SOURCE},
1285 {"depends", 1, (opkg_cmd_fun_t) opkg_depends_cmd,
1286 PFM_DESCRIPTION | PFM_SOURCE},
1287 {"whatdepends", 1, (opkg_cmd_fun_t) opkg_whatdepends_cmd,
1288 PFM_DESCRIPTION | PFM_SOURCE},
1289 {"whatdependsrec", 1, (opkg_cmd_fun_t) opkg_whatdepends_recursively_cmd,
1290 PFM_DESCRIPTION | PFM_SOURCE},
1291 {"whatrecommends", 1, (opkg_cmd_fun_t) opkg_whatrecommends_cmd,
1292 PFM_DESCRIPTION | PFM_SOURCE},
1293 {"whatsuggests", 1, (opkg_cmd_fun_t) opkg_whatsuggests_cmd,
1294 PFM_DESCRIPTION | PFM_SOURCE},
1295 {"whatprovides", 1, (opkg_cmd_fun_t) opkg_whatprovides_cmd,
1296 PFM_DESCRIPTION | PFM_SOURCE},
1297 {"whatreplaces", 1, (opkg_cmd_fun_t) opkg_whatreplaces_cmd,
1298 PFM_DESCRIPTION | PFM_SOURCE},
1299 {"whatconflicts", 1, (opkg_cmd_fun_t) opkg_whatconflicts_cmd,
1300 PFM_DESCRIPTION | PFM_SOURCE},
1303 opkg_cmd_t *opkg_cmd_find(const char *name)
1307 int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
1309 for (i = 0; i < num_cmds; i++) {
1311 if (strcmp(name, cmd->name) == 0)
1318 int opkg_cmd_exec(opkg_cmd_t * cmd, int argc, const char **argv)
1320 return (cmd->fun) (argc, argv);