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 signal(SIGINT, sigint_handler);
441 * Now scan through package names and install
443 for (i = 0; i < argc; i++) {
446 opkg_msg(DEBUG2, "%s\n", arg);
447 if (opkg_prepare_url_for_install(arg, &argv[i]))
451 pkg_hash_load_package_details();
452 pkg_hash_load_status_files();
454 if (conf->force_reinstall) {
455 int saved_force_depends = conf->force_depends;
456 conf->force_depends = 1;
457 (void)opkg_remove_cmd(argc, argv);
458 conf->force_depends = saved_force_depends;
459 conf->force_reinstall = 0;
462 pkg_info_preinstall_check();
464 for (i = 0; i < argc; i++) {
466 if (opkg_install_by_name(arg)) {
467 opkg_msg(ERROR, "Cannot install package %s.\n", arg);
472 if (opkg_configure_packages(NULL))
475 write_status_files_if_changed();
480 static int opkg_upgrade_cmd(int argc, char **argv)
486 signal(SIGINT, sigint_handler);
489 for (i = 0; i < argc; i++) {
492 if (opkg_prepare_url_for_install(arg, &arg))
495 pkg_info_preinstall_check();
497 for (i = 0; i < argc; i++) {
499 if (conf->restrict_to_default_dest) {
501 pkg_hash_fetch_installed_by_name_dest(argv
507 "Package %s not installed in %s.\n",
509 conf->default_dest->name);
513 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
516 if (opkg_upgrade_pkg(pkg))
519 if (opkg_install_by_name(arg))
525 if (opkg_configure_packages(NULL))
528 write_status_files_if_changed();
533 static int opkg_download_cmd(int argc, char **argv)
539 pkg_info_preinstall_check();
540 for (i = 0; i < argc; i++) {
543 pkg = pkg_hash_fetch_best_installation_candidate_by_name(arg);
545 opkg_msg(ERROR, "Cannot find package %s.\n", arg);
549 if (opkg_download_pkg(pkg, "."))
553 opkg_msg(ERROR, "Failed to download %s.\n", pkg->name);
555 opkg_msg(NOTICE, "Downloaded %s as %s.\n",
556 pkg->name, pkg_get_string(pkg, PKG_LOCAL_FILENAME));
563 static int opkg_list_find_cmd(int argc, char **argv, int use_desc)
566 pkg_vec_t *available;
568 char *pkg_name = NULL;
574 available = pkg_vec_alloc();
575 pkg_hash_fetch_available(available);
576 pkg_vec_sort(available, pkg_compare_names);
577 for (i = 0; i < available->len; i++) {
578 pkg = available->pkgs[i];
579 description = use_desc ? pkg_get_string(pkg, PKG_DESCRIPTION) : NULL;
580 /* if we have package name or pattern and pkg does not match, then skip it */
581 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase) &&
582 (!use_desc || !description
583 || fnmatch(pkg_name, description, conf->nocase)))
587 pkg_vec_free(available);
592 static int opkg_list_cmd(int argc, char **argv)
594 return opkg_list_find_cmd(argc, argv, 0);
597 static int opkg_find_cmd(int argc, char **argv)
599 return opkg_list_find_cmd(argc, argv, 1);
602 static int opkg_list_installed_cmd(int argc, char **argv)
605 pkg_vec_t *available;
607 char *pkg_name = NULL;
612 available = pkg_vec_alloc();
613 pkg_hash_fetch_all_installed(available);
614 pkg_vec_sort(available, pkg_compare_names);
615 for (i = 0; i < available->len; i++) {
616 pkg = available->pkgs[i];
617 /* if we have package name or pattern and pkg does not match, then skip it */
618 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
623 pkg_vec_free(available);
628 static int opkg_list_changed_conffiles_cmd(int argc, char **argv)
631 pkg_vec_t *available;
633 char *pkg_name = NULL;
634 conffile_list_elt_t *iter;
641 available = pkg_vec_alloc();
642 pkg_hash_fetch_all_installed(available);
643 pkg_vec_sort(available, pkg_compare_names);
644 for (i = 0; i < available->len; i++) {
645 pkg = available->pkgs[i];
646 cl = pkg_get_ptr(pkg, PKG_CONFFILES);
647 /* if we have package name or pattern and pkg does not match, then skip it */
648 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
650 if (!cl || nv_pair_list_empty(cl))
652 for (iter = nv_pair_list_first(cl); iter;
653 iter = nv_pair_list_next(cl, iter)) {
654 cf = (conffile_t *) iter->data;
655 if (cf->name && cf->value
656 && conffile_has_been_modified(cf))
657 printf("%s\n", cf->name);
660 pkg_vec_free(available);
664 static int opkg_list_upgradable_cmd(int argc, char **argv)
666 struct active_list *head = prepare_upgrade_list();
667 struct active_list *node = NULL;
668 pkg_t *_old_pkg, *_new_pkg;
670 for (node = active_list_next(head, head); node;
671 node = active_list_next(head, node)) {
672 _old_pkg = node->pkg;
674 pkg_hash_fetch_best_installation_candidate_by_name
676 if (_new_pkg == NULL)
678 old_v = pkg_version_str_alloc(_old_pkg);
679 new_v = pkg_version_str_alloc(_new_pkg);
680 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
684 active_list_head_delete(head);
688 static int opkg_info_status_cmd(int argc, char **argv, int installed_only)
691 pkg_vec_t *available;
693 char *pkg_name = NULL;
700 available = pkg_vec_alloc();
702 pkg_hash_fetch_all_installed(available);
704 pkg_hash_fetch_available(available);
706 for (i = 0; i < available->len; i++) {
707 pkg = available->pkgs[i];
708 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) {
712 pkg_formatted_info(stdout, pkg);
714 cl = pkg_get_ptr(pkg, PKG_CONFFILES);
716 if (conf->verbosity >= NOTICE && cl) {
717 conffile_list_elt_t *iter;
718 for (iter = nv_pair_list_first(cl); iter;
719 iter = nv_pair_list_next(cl, iter)) {
720 conffile_t *cf = (conffile_t *) iter->data;
721 int modified = conffile_has_been_modified(cf);
724 "conffile=%s md5sum=%s modified=%d.\n",
725 cf->name, cf->value, modified);
729 pkg_vec_free(available);
734 static int opkg_info_cmd(int argc, char **argv)
736 return opkg_info_status_cmd(argc, argv, 0);
739 static int opkg_status_cmd(int argc, char **argv)
741 return opkg_info_status_cmd(argc, argv, 1);
744 static int opkg_configure_cmd(int argc, char **argv)
747 char *pkg_name = NULL;
752 err = opkg_configure_packages(pkg_name);
754 write_status_files_if_changed();
759 static int opkg_remove_cmd(int argc, char **argv)
761 int i, a, done, err = 0;
763 pkg_t *pkg_to_remove;
764 pkg_vec_t *available;
768 signal(SIGINT, sigint_handler);
770 pkg_info_preinstall_check();
772 available = pkg_vec_alloc();
773 pkg_hash_fetch_all_installed(available);
775 for (i = 0; i < argc; i++) {
776 for (a = 0; a < available->len; a++) {
777 pkg = available->pkgs[a];
778 if (fnmatch(argv[i], pkg->name, conf->nocase)) {
781 if (conf->restrict_to_default_dest) {
783 pkg_hash_fetch_installed_by_name_dest(pkg->
789 pkg_hash_fetch_installed_by_name(pkg->name);
792 if (pkg_to_remove == NULL) {
794 "Package %s is not installed.\n",
798 if (pkg->state_status == SS_NOT_INSTALLED) {
799 opkg_msg(ERROR, "Package %s not installed.\n",
804 if (opkg_remove_pkg(pkg_to_remove, 0))
811 pkg_vec_free(available);
814 opkg_msg(NOTICE, "No packages removed.\n");
816 write_status_files_if_changed();
820 static int opkg_flag_cmd(int argc, char **argv)
824 const char *flags = argv[0];
826 signal(SIGINT, sigint_handler);
828 for (i = 1; i < argc; i++) {
829 if (conf->restrict_to_default_dest) {
830 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
834 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
838 opkg_msg(ERROR, "Package %s is not installed.\n",
842 if ((strcmp(flags, "hold") == 0)
843 || (strcmp(flags, "noprune") == 0)
844 || (strcmp(flags, "user") == 0)
845 || (strcmp(flags, "ok") == 0)) {
846 pkg->state_flag = pkg_state_flag_from_str(flags);
850 * Useful if a package is installed in an offline_root, and
851 * should be configured by opkg-cl configure at a later date.
853 if ((strcmp(flags, "installed") == 0)
854 || (strcmp(flags, "unpacked") == 0)) {
855 pkg->state_status = pkg_state_status_from_str(flags);
858 opkg_state_changed++;
859 opkg_msg(NOTICE, "Setting flags for package %s to %s.\n",
863 write_status_files_if_changed();
867 static int opkg_files_cmd(int argc, char **argv)
871 str_list_elt_t *iter;
878 pkg = pkg_hash_fetch_installed_by_name(argv[0]);
880 opkg_msg(ERROR, "Package %s not installed.\n", argv[0]);
884 files = pkg_get_installed_files(pkg);
885 pkg_version = pkg_version_str_alloc(pkg);
888 ("Package %s (%s) is installed on %s and has the following files:\n",
889 pkg->name, pkg_version, pkg->dest->name);
891 for (iter = str_list_first(files); iter;
892 iter = str_list_next(files, iter))
893 printf("%s\n", (char *)iter->data);
896 pkg_free_installed_files(pkg);
901 static int opkg_depends_cmd(int argc, char **argv)
904 pkg_vec_t *available_pkgs;
905 compound_depend_t *cdep;
909 pkg_info_preinstall_check();
911 available_pkgs = pkg_vec_alloc();
913 pkg_hash_fetch_available(available_pkgs);
915 pkg_hash_fetch_all_installed(available_pkgs);
917 for (i = 0; i < argc; i++) {
918 for (j = 0; j < available_pkgs->len; j++) {
919 pkg = available_pkgs->pkgs[j];
921 if (fnmatch(argv[i], pkg->name, conf->nocase) != 0)
924 opkg_msg(NOTICE, "%s depends on:\n", pkg->name);
926 for (k = 0, cdep = pkg_get_ptr(pkg, PKG_DEPENDS); cdep && cdep->type; k++, cdep++) {
927 if (cdep->type != DEPEND)
930 str = pkg_depend_str(pkg, k);
931 opkg_msg(NOTICE, "\t%s\n", str);
938 pkg_vec_free(available_pkgs);
942 static int pkg_mark_provides(pkg_t * pkg)
944 abstract_pkg_t **provider = pkg_get_ptr(pkg, PKG_PROVIDES);
946 pkg->parent->state_flag |= SF_MARKED;
948 while (provider && *provider) {
949 (*provider)->state_flag |= SF_MARKED;
956 enum what_field_type {
966 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive,
967 int argc, char **argv)
969 depend_t *possibility;
970 compound_depend_t *cdep, *deps;
971 pkg_vec_t *available_pkgs;
975 const char *rel_str = NULL;
978 switch (what_field_type) {
980 rel_str = "depends on";
983 rel_str = "conflicts with";
986 rel_str = "suggests";
989 rel_str = "recommends";
995 available_pkgs = pkg_vec_alloc();
998 pkg_hash_fetch_available(available_pkgs);
1000 pkg_hash_fetch_all_installed(available_pkgs);
1002 /* mark the root set */
1003 pkg_vec_clear_marks(available_pkgs);
1004 opkg_msg(NOTICE, "Root set:\n");
1005 for (i = 0; i < argc; i++)
1006 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
1008 for (i = 0; i < available_pkgs->len; i++) {
1009 pkg = available_pkgs->pkgs[i];
1010 if (pkg->state_flag & SF_MARKED) {
1011 /* mark the parent (abstract) package */
1012 pkg_mark_provides(pkg);
1013 opkg_msg(NOTICE, " %s\n", pkg->name);
1017 opkg_msg(NOTICE, "What %s root set\n", rel_str);
1021 for (j = 0; j < available_pkgs->len; j++) {
1023 pkg = available_pkgs->pkgs[j];
1025 count = ((what_field_type == CONFLICTS)
1026 ? pkg->conflicts_count
1027 : pkg->pre_depends_count +
1028 pkg->depends_count +
1029 pkg->recommends_count + pkg->suggests_count);
1032 /* skip this package if it is already marked */
1033 if (pkg->parent->state_flag & SF_MARKED)
1036 deps = pkg_get_ptr(pkg, (what_field_type == CONFLICTS) ? PKG_CONFLICTS : PKG_DEPENDS);
1038 for (cdep = deps; cdep->type; cdep++) {
1039 if (what_field_type != cdep->type)
1042 for (l = 0; l < cdep->possibility_count; l++) {
1043 possibility = cdep->possibilities[l];
1045 if ((possibility->pkg->state_flag
1050 /* mark the depending package so we
1051 * won't visit it again */
1052 pkg->state_flag |= SF_MARKED;
1053 pkg_mark_provides(pkg);
1056 ver = pkg_version_str_alloc(pkg);
1057 opkg_msg(NOTICE, "\t%s %s\t%s %s",
1061 possibility->pkg->name);
1063 if (possibility->version) {
1064 opkg_msg(NOTICE, " (%s%s)",
1068 possibility->version);
1070 if (!pkg_dependence_satisfiable
1074 opkg_message(NOTICE, "\n");
1081 } while (changed && recursive);
1083 pkg_vec_free(available_pkgs);
1088 static int opkg_whatdepends_recursively_cmd(int argc, char **argv)
1090 return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv);
1093 static int opkg_whatdepends_cmd(int argc, char **argv)
1095 return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv);
1098 static int opkg_whatsuggests_cmd(int argc, char **argv)
1100 return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv);
1103 static int opkg_whatrecommends_cmd(int argc, char **argv)
1105 return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv);
1108 static int opkg_whatconflicts_cmd(int argc, char **argv)
1110 return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv);
1114 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc,
1117 abstract_pkg_t *apkg, **abpkgs;
1120 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1121 const char *rel_str =
1122 (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1125 pkg_info_preinstall_check();
1127 if (conf->query_all)
1128 pkg_hash_fetch_available(available_pkgs);
1130 pkg_hash_fetch_all_installed(available_pkgs);
1131 for (i = 0; i < argc; i++) {
1132 const char *target = argv[i];
1135 opkg_msg(NOTICE, "What %s %s\n", rel_str, target);
1136 for (j = 0; j < available_pkgs->len; j++) {
1137 pkg_t *pkg = available_pkgs->pkgs[j];
1138 abpkgs = pkg_get_ptr(pkg, (what_field_type == WHATPROVIDES) ? PKG_PROVIDES : PKG_REPLACES);
1140 while (abpkgs && *abpkgs) {
1143 if (fnmatch(target, apkg->name, conf->nocase))
1146 opkg_msg(NOTICE, " %s", pkg->name);
1148 if ((conf->nocase ? strcasecmp(target, apkg->name)
1149 : strcmp(target, apkg->name)))
1150 opkg_msg(NOTICE, "\t%s %s\n", rel_str, apkg->name);
1152 opkg_message(NOTICE, "\n");
1157 pkg_vec_free(available_pkgs);
1162 static int opkg_whatprovides_cmd(int argc, char **argv)
1164 return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv);
1167 static int opkg_whatreplaces_cmd(int argc, char **argv)
1169 return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv);
1172 static int opkg_search_cmd(int argc, char **argv)
1176 pkg_vec_t *installed;
1178 str_list_t *installed_files;
1179 str_list_elt_t *iter;
1180 char *installed_file;
1186 installed = pkg_vec_alloc();
1187 pkg_hash_fetch_all_installed(installed);
1188 pkg_vec_sort(installed, pkg_compare_names);
1190 for (i = 0; i < installed->len; i++) {
1191 pkg = installed->pkgs[i];
1193 installed_files = pkg_get_installed_files(pkg);
1195 for (iter = str_list_first(installed_files); iter;
1196 iter = str_list_next(installed_files, iter)) {
1197 installed_file = (char *)iter->data;
1198 if (fnmatch(argv[0], installed_file, conf->nocase) == 0)
1202 pkg_free_installed_files(pkg);
1205 pkg_vec_free(installed);
1210 static int opkg_compare_versions_cmd(int argc, char **argv)
1213 /* this is a bit gross */
1215 parse_version(&p1, argv[0]);
1216 parse_version(&p2, argv[2]);
1217 return pkg_version_satisfied(&p1, &p2, argv[1]);
1220 "opkg compare_versions <v1> <op> <v2>\n"
1221 "<op> is one of <= >= << >> =\n");
1226 static int opkg_print_architecture_cmd(int argc, char **argv)
1228 nv_pair_list_elt_t *l;
1230 list_for_each_entry(l, &conf->arch_list.head, node) {
1231 nv_pair_t *nv = (nv_pair_t *) l->data;
1232 printf("arch %s %s\n", nv->name, nv->value);
1237 /* XXX: CLEANUP: The usage strings should be incorporated into this
1238 array for easier maintenance */
1239 static opkg_cmd_t cmds[] = {
1240 {"update", 0, (opkg_cmd_fun_t) opkg_update_cmd,
1241 PFM_DESCRIPTION | PFM_SOURCE},
1242 {"upgrade", 1, (opkg_cmd_fun_t) opkg_upgrade_cmd,
1243 PFM_DESCRIPTION | PFM_SOURCE},
1244 {"list", 0, (opkg_cmd_fun_t) opkg_list_cmd, PFM_SOURCE},
1245 {"list_installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1247 {"list-installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1249 {"list_upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1251 {"list-upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1253 {"list_changed_conffiles", 0,
1254 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1255 {"list-changed-conffiles", 0,
1256 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1257 {"info", 0, (opkg_cmd_fun_t) opkg_info_cmd, 0},
1258 {"flag", 1, (opkg_cmd_fun_t) opkg_flag_cmd,
1259 PFM_DESCRIPTION | PFM_SOURCE},
1260 {"status", 0, (opkg_cmd_fun_t) opkg_status_cmd,
1261 PFM_DESCRIPTION | PFM_SOURCE},
1262 {"install", 1, (opkg_cmd_fun_t) opkg_install_cmd,
1263 PFM_DESCRIPTION | PFM_SOURCE},
1264 {"remove", 1, (opkg_cmd_fun_t) opkg_remove_cmd,
1265 PFM_DESCRIPTION | PFM_SOURCE},
1266 {"configure", 0, (opkg_cmd_fun_t) opkg_configure_cmd,
1267 PFM_DESCRIPTION | PFM_SOURCE},
1268 {"files", 1, (opkg_cmd_fun_t) opkg_files_cmd,
1269 PFM_DESCRIPTION | PFM_SOURCE},
1270 {"search", 1, (opkg_cmd_fun_t) opkg_search_cmd,
1271 PFM_DESCRIPTION | PFM_SOURCE},
1272 {"find", 1, (opkg_cmd_fun_t) opkg_find_cmd, PFM_SOURCE},
1273 {"download", 1, (opkg_cmd_fun_t) opkg_download_cmd,
1274 PFM_DESCRIPTION | PFM_SOURCE},
1275 {"compare_versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd,
1276 PFM_DESCRIPTION | PFM_SOURCE},
1277 {"compare-versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd,
1278 PFM_DESCRIPTION | PFM_SOURCE},
1279 {"print-architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1280 PFM_DESCRIPTION | PFM_SOURCE},
1281 {"print_architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1282 PFM_DESCRIPTION | PFM_SOURCE},
1283 {"print-installation-architecture", 0,
1284 (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1285 PFM_DESCRIPTION | PFM_SOURCE},
1286 {"print_installation_architecture", 0,
1287 (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1288 PFM_DESCRIPTION | PFM_SOURCE},
1289 {"depends", 1, (opkg_cmd_fun_t) opkg_depends_cmd,
1290 PFM_DESCRIPTION | PFM_SOURCE},
1291 {"whatdepends", 1, (opkg_cmd_fun_t) opkg_whatdepends_cmd,
1292 PFM_DESCRIPTION | PFM_SOURCE},
1293 {"whatdependsrec", 1, (opkg_cmd_fun_t) opkg_whatdepends_recursively_cmd,
1294 PFM_DESCRIPTION | PFM_SOURCE},
1295 {"whatrecommends", 1, (opkg_cmd_fun_t) opkg_whatrecommends_cmd,
1296 PFM_DESCRIPTION | PFM_SOURCE},
1297 {"whatsuggests", 1, (opkg_cmd_fun_t) opkg_whatsuggests_cmd,
1298 PFM_DESCRIPTION | PFM_SOURCE},
1299 {"whatprovides", 1, (opkg_cmd_fun_t) opkg_whatprovides_cmd,
1300 PFM_DESCRIPTION | PFM_SOURCE},
1301 {"whatreplaces", 1, (opkg_cmd_fun_t) opkg_whatreplaces_cmd,
1302 PFM_DESCRIPTION | PFM_SOURCE},
1303 {"whatconflicts", 1, (opkg_cmd_fun_t) opkg_whatconflicts_cmd,
1304 PFM_DESCRIPTION | PFM_SOURCE},
1307 opkg_cmd_t *opkg_cmd_find(const char *name)
1311 int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
1313 for (i = 0; i < num_cmds; i++) {
1315 if (strcmp(name, cmd->name) == 0)
1322 int opkg_cmd_exec(opkg_cmd_t * cmd, int argc, const char **argv)
1324 return (cmd->fun) (argc, argv);