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)
290 compound_depend_t *compound_depend;
291 depend_t **possible_satisfiers;
292 abstract_pkg_t *abpkg;
293 abstract_pkg_t **dependents;
295 /* If it's just an available package, that is, not installed and not even
297 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
298 would do here. However, if there is an intermediate node (pkg) that is
299 configured and installed between two unpacked packages, the latter
300 won't be properly reordered, unless all installed/unpacked pkgs are
302 if (pkg->state_status == SS_NOT_INSTALLED)
305 /* If the package has already been visited (by this function), skip it */
306 for (j = 0; j < visited->len; j++)
307 if (!strcmp(visited->pkgs[j]->name, pkg->name)) {
308 opkg_msg(DEBUG, "pkg %s already visited, skipping.\n",
313 pkg_vec_insert(visited, pkg);
315 count = pkg->pre_depends_count + pkg->depends_count +
316 pkg->recommends_count + pkg->suggests_count;
318 opkg_msg(DEBUG, "pkg %s.\n", pkg->name);
320 /* Iterate over all the dependencies of pkg. For each one, find a package
321 that is either installed or unpacked and satisfies this dependency.
322 (there should only be one such package per dependency installed or
323 unpacked). Then recurse to the dependency package */
324 for (j = 0; j < count; j++) {
325 compound_depend = &pkg->depends[j];
326 possible_satisfiers = compound_depend->possibilities;
327 for (k = 0; k < compound_depend->possibility_count; k++) {
328 abpkg = possible_satisfiers[k]->pkg;
329 dependents = abpkg->provided_by->pkgs;
331 if (dependents != NULL)
332 while (l < abpkg->provided_by->len
333 && dependents[l] != NULL) {
335 "Descending on pkg %s.\n",
336 dependents[l]->name);
338 /* find whether dependent l is installed or unpacked,
339 * and then find which package in the list satisfies it */
340 for (m = 0; m < all->len; m++) {
342 if (dep->state_status !=
348 opkg_recurse_pkgs_in_order
352 /* Stop the outer loop */
356 /* break from the inner loop */
365 /* When all recursions from this node down, are over, and all
366 dependencies have been added in proper order in the ordered array, add
367 also the package pkg to ordered array */
368 pkg_vec_insert(ordered, pkg);
374 static int opkg_configure_packages(char *pkg_name)
376 pkg_vec_t *all, *ordered, *visited;
382 opkg_msg(INFO, "Configuring unpacked packages.\n");
384 all = pkg_vec_alloc();
386 pkg_hash_fetch_available(all);
388 /* Reorder pkgs in order to be configured according to the Depends: tag
390 opkg_msg(INFO, "Reordering packages before configuring them...\n");
391 ordered = pkg_vec_alloc();
392 visited = pkg_vec_alloc();
393 for (i = 0; i < all->len; i++) {
395 opkg_recurse_pkgs_in_order(pkg, all, visited, ordered);
398 ic = opkg_prep_intercepts();
404 for (i = 0; i < ordered->len; i++) {
405 pkg = ordered->pkgs[i];
407 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
410 if (pkg->state_status == SS_UNPACKED) {
411 opkg_msg(NOTICE, "Configuring %s.\n", pkg->name);
412 r = opkg_configure(pkg);
414 pkg->state_status = SS_INSTALLED;
415 pkg->parent->state_status = SS_INSTALLED;
416 pkg->state_flag &= ~SF_PREFER;
417 opkg_state_changed++;
424 if (opkg_finalize_intercepts(ic))
429 pkg_vec_free(ordered);
430 pkg_vec_free(visited);
435 static int opkg_remove_cmd(int argc, char **argv);
437 static int opkg_install_cmd(int argc, char **argv)
443 if (conf->force_reinstall) {
444 int saved_force_depends = conf->force_depends;
445 conf->force_depends = 1;
446 (void)opkg_remove_cmd(argc, argv);
447 conf->force_depends = saved_force_depends;
448 conf->force_reinstall = 0;
451 signal(SIGINT, sigint_handler);
454 * Now scan through package names and install
456 for (i = 0; i < argc; i++) {
459 opkg_msg(DEBUG2, "%s\n", arg);
460 if (opkg_prepare_url_for_install(arg, &argv[i]))
463 pkg_info_preinstall_check();
465 for (i = 0; i < argc; i++) {
467 if (opkg_install_by_name(arg)) {
468 opkg_msg(ERROR, "Cannot install package %s.\n", arg);
473 if (opkg_configure_packages(NULL))
476 write_status_files_if_changed();
481 static int opkg_upgrade_cmd(int argc, char **argv)
487 signal(SIGINT, sigint_handler);
490 for (i = 0; i < argc; i++) {
493 if (opkg_prepare_url_for_install(arg, &arg))
496 pkg_info_preinstall_check();
498 for (i = 0; i < argc; i++) {
500 if (conf->restrict_to_default_dest) {
502 pkg_hash_fetch_installed_by_name_dest(argv
508 "Package %s not installed in %s.\n",
510 conf->default_dest->name);
514 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
517 if (opkg_upgrade_pkg(pkg))
520 if (opkg_install_by_name(arg))
526 if (opkg_configure_packages(NULL))
529 write_status_files_if_changed();
534 static int opkg_download_cmd(int argc, char **argv)
540 pkg_info_preinstall_check();
541 for (i = 0; i < argc; i++) {
544 pkg = pkg_hash_fetch_best_installation_candidate_by_name(arg);
546 opkg_msg(ERROR, "Cannot find package %s.\n", arg);
550 if (opkg_download_pkg(pkg, "."))
554 opkg_msg(ERROR, "Failed to download %s.\n", pkg->name);
556 opkg_msg(NOTICE, "Downloaded %s as %s.\n",
557 pkg->name, pkg_get_string(pkg, PKG_LOCAL_FILENAME));
564 static int opkg_list_find_cmd(int argc, char **argv, int use_desc)
567 pkg_vec_t *available;
569 char *pkg_name = NULL;
575 available = pkg_vec_alloc();
576 pkg_hash_fetch_available(available);
577 pkg_vec_sort(available, pkg_compare_names);
578 for (i = 0; i < available->len; i++) {
579 pkg = available->pkgs[i];
580 description = use_desc ? pkg_get_string(pkg, PKG_DESCRIPTION) : NULL;
581 /* if we have package name or pattern and pkg does not match, then skip it */
582 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase) &&
583 (!use_desc || !description
584 || fnmatch(pkg_name, description, conf->nocase)))
588 pkg_vec_free(available);
593 static int opkg_list_cmd(int argc, char **argv)
595 return opkg_list_find_cmd(argc, argv, 0);
598 static int opkg_find_cmd(int argc, char **argv)
600 return opkg_list_find_cmd(argc, argv, 1);
603 static int opkg_list_installed_cmd(int argc, char **argv)
606 pkg_vec_t *available;
608 char *pkg_name = NULL;
613 available = pkg_vec_alloc();
614 pkg_hash_fetch_all_installed(available);
615 pkg_vec_sort(available, pkg_compare_names);
616 for (i = 0; i < available->len; i++) {
617 pkg = available->pkgs[i];
618 /* if we have package name or pattern and pkg does not match, then skip it */
619 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
624 pkg_vec_free(available);
629 static int opkg_list_changed_conffiles_cmd(int argc, char **argv)
632 pkg_vec_t *available;
634 char *pkg_name = NULL;
635 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 /* if we have package name or pattern and pkg does not match, then skip it */
647 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
649 if (nv_pair_list_empty(&pkg->conffiles))
651 for (iter = nv_pair_list_first(&pkg->conffiles); iter;
652 iter = nv_pair_list_next(&pkg->conffiles, iter)) {
653 cf = (conffile_t *) iter->data;
654 if (cf->name && cf->value
655 && conffile_has_been_modified(cf))
656 printf("%s\n", cf->name);
659 pkg_vec_free(available);
663 static int opkg_list_upgradable_cmd(int argc, char **argv)
665 struct active_list *head = prepare_upgrade_list();
666 struct active_list *node = NULL;
667 pkg_t *_old_pkg, *_new_pkg;
669 for (node = active_list_next(head, head); node;
670 node = active_list_next(head, node)) {
671 _old_pkg = list_entry(node, pkg_t, list);
673 pkg_hash_fetch_best_installation_candidate_by_name
675 if (_new_pkg == NULL)
677 old_v = pkg_version_str_alloc(_old_pkg);
678 new_v = pkg_version_str_alloc(_new_pkg);
679 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
683 active_list_head_delete(head);
687 static int opkg_info_status_cmd(int argc, char **argv, int installed_only)
690 pkg_vec_t *available;
692 char *pkg_name = NULL;
698 available = pkg_vec_alloc();
700 pkg_hash_fetch_all_installed(available);
702 pkg_hash_fetch_available(available);
704 for (i = 0; i < available->len; i++) {
705 pkg = available->pkgs[i];
706 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) {
710 pkg_formatted_info(stdout, pkg);
712 if (conf->verbosity >= NOTICE) {
713 conffile_list_elt_t *iter;
714 for (iter = nv_pair_list_first(&pkg->conffiles); iter;
715 iter = nv_pair_list_next(&pkg->conffiles, 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)
901 pkg_vec_t *available_pkgs;
902 compound_depend_t *cdep;
906 pkg_info_preinstall_check();
908 available_pkgs = pkg_vec_alloc();
910 pkg_hash_fetch_available(available_pkgs);
912 pkg_hash_fetch_all_installed(available_pkgs);
914 for (i = 0; i < argc; i++) {
915 for (j = 0; j < available_pkgs->len; j++) {
916 pkg = available_pkgs->pkgs[j];
918 if (fnmatch(argv[i], pkg->name, conf->nocase) != 0)
921 depends_count = pkg->depends_count +
922 pkg->pre_depends_count +
923 pkg->recommends_count + pkg->suggests_count;
925 opkg_msg(NOTICE, "%s depends on:\n", pkg->name);
927 for (k = 0; k < depends_count; k++) {
928 cdep = &pkg->depends[k];
930 if (cdep->type != DEPEND)
933 str = pkg_depend_str(pkg, k);
934 opkg_msg(NOTICE, "\t%s\n", str);
941 pkg_vec_free(available_pkgs);
945 static int pkg_mark_provides(pkg_t * pkg)
947 int provides_count = pkg->provides_count;
948 abstract_pkg_t **provides = pkg->provides;
950 pkg->parent->state_flag |= SF_MARKED;
951 for (i = 0; i < provides_count; i++) {
952 provides[i]->state_flag |= SF_MARKED;
957 enum what_field_type {
967 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive,
968 int argc, char **argv)
970 depend_t *possibility;
971 compound_depend_t *cdep;
972 pkg_vec_t *available_pkgs;
976 const char *rel_str = NULL;
979 switch (what_field_type) {
981 rel_str = "depends on";
984 rel_str = "conflicts with";
987 rel_str = "suggests";
990 rel_str = "recommends";
996 available_pkgs = pkg_vec_alloc();
999 pkg_hash_fetch_available(available_pkgs);
1001 pkg_hash_fetch_all_installed(available_pkgs);
1003 /* mark the root set */
1004 pkg_vec_clear_marks(available_pkgs);
1005 opkg_msg(NOTICE, "Root set:\n");
1006 for (i = 0; i < argc; i++)
1007 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
1009 for (i = 0; i < available_pkgs->len; i++) {
1010 pkg = available_pkgs->pkgs[i];
1011 if (pkg->state_flag & SF_MARKED) {
1012 /* mark the parent (abstract) package */
1013 pkg_mark_provides(pkg);
1014 opkg_msg(NOTICE, " %s\n", pkg->name);
1018 opkg_msg(NOTICE, "What %s root set\n", rel_str);
1022 for (j = 0; j < available_pkgs->len; j++) {
1024 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);
1031 /* skip this package if it is already marked */
1032 if (pkg->parent->state_flag & SF_MARKED)
1035 for (k = 0; k < count; k++) {
1036 cdep = (what_field_type == CONFLICTS)
1037 ? &pkg->conflicts[k]
1040 if (what_field_type != cdep->type)
1043 for (l = 0; l < cdep->possibility_count; l++) {
1044 possibility = cdep->possibilities[l];
1046 if ((possibility->pkg->state_flag
1051 /* mark the depending package so we
1052 * won't visit it again */
1053 pkg->state_flag |= SF_MARKED;
1054 pkg_mark_provides(pkg);
1057 ver = pkg_version_str_alloc(pkg);
1058 opkg_msg(NOTICE, "\t%s %s\t%s %s",
1062 possibility->pkg->name);
1064 if (possibility->version) {
1065 opkg_msg(NOTICE, " (%s%s)",
1069 possibility->version);
1071 if (!pkg_dependence_satisfiable
1075 opkg_message(NOTICE, "\n");
1082 } while (changed && recursive);
1084 pkg_vec_free(available_pkgs);
1089 static int opkg_whatdepends_recursively_cmd(int argc, char **argv)
1091 return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv);
1094 static int opkg_whatdepends_cmd(int argc, char **argv)
1096 return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv);
1099 static int opkg_whatsuggests_cmd(int argc, char **argv)
1101 return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv);
1104 static int opkg_whatrecommends_cmd(int argc, char **argv)
1106 return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv);
1109 static int opkg_whatconflicts_cmd(int argc, char **argv)
1111 return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv);
1115 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc,
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];
1141 WHATPROVIDES) ? pkg->provides_count : pkg->
1143 for (k = 0; k < count; k++) {
1144 abstract_pkg_t *apkg =
1145 ((what_field_type == WHATPROVIDES)
1147 : pkg->replaces[k]);
1149 (target, apkg->name,
1150 conf->nocase) == 0) {
1151 opkg_msg(NOTICE, " %s",
1154 nocase ? strcasecmp(target,
1163 opkg_message(NOTICE, "\n");
1168 pkg_vec_free(available_pkgs);
1173 static int opkg_whatprovides_cmd(int argc, char **argv)
1175 return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv);
1178 static int opkg_whatreplaces_cmd(int argc, char **argv)
1180 return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv);
1183 static int opkg_search_cmd(int argc, char **argv)
1187 pkg_vec_t *installed;
1189 str_list_t *installed_files;
1190 str_list_elt_t *iter;
1191 char *installed_file;
1197 installed = pkg_vec_alloc();
1198 pkg_hash_fetch_all_installed(installed);
1199 pkg_vec_sort(installed, pkg_compare_names);
1201 for (i = 0; i < installed->len; i++) {
1202 pkg = installed->pkgs[i];
1204 installed_files = pkg_get_installed_files(pkg);
1206 for (iter = str_list_first(installed_files); iter;
1207 iter = str_list_next(installed_files, iter)) {
1208 installed_file = (char *)iter->data;
1209 if (fnmatch(argv[0], installed_file, conf->nocase) == 0)
1213 pkg_free_installed_files(pkg);
1216 pkg_vec_free(installed);
1221 static int opkg_compare_versions_cmd(int argc, char **argv)
1224 /* this is a bit gross */
1226 parse_version(&p1, argv[0]);
1227 parse_version(&p2, argv[2]);
1228 return pkg_version_satisfied(&p1, &p2, argv[1]);
1231 "opkg compare_versions <v1> <op> <v2>\n"
1232 "<op> is one of <= >= << >> =\n");
1237 static int opkg_print_architecture_cmd(int argc, char **argv)
1239 nv_pair_list_elt_t *l;
1241 list_for_each_entry(l, &conf->arch_list.head, node) {
1242 nv_pair_t *nv = (nv_pair_t *) l->data;
1243 printf("arch %s %s\n", nv->name, nv->value);
1248 /* XXX: CLEANUP: The usage strings should be incorporated into this
1249 array for easier maintenance */
1250 static opkg_cmd_t cmds[] = {
1251 {"update", 0, (opkg_cmd_fun_t) opkg_update_cmd,
1252 PFM_DESCRIPTION | PFM_SOURCE},
1253 {"upgrade", 1, (opkg_cmd_fun_t) opkg_upgrade_cmd,
1254 PFM_DESCRIPTION | PFM_SOURCE},
1255 {"list", 0, (opkg_cmd_fun_t) opkg_list_cmd, PFM_SOURCE},
1256 {"list_installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1258 {"list-installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1260 {"list_upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1262 {"list-upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1264 {"list_changed_conffiles", 0,
1265 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1266 {"list-changed-conffiles", 0,
1267 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1268 {"info", 0, (opkg_cmd_fun_t) opkg_info_cmd, 0},
1269 {"flag", 1, (opkg_cmd_fun_t) opkg_flag_cmd,
1270 PFM_DESCRIPTION | PFM_SOURCE},
1271 {"status", 0, (opkg_cmd_fun_t) opkg_status_cmd,
1272 PFM_DESCRIPTION | PFM_SOURCE},
1273 {"install", 1, (opkg_cmd_fun_t) opkg_install_cmd,
1274 PFM_DESCRIPTION | PFM_SOURCE},
1275 {"remove", 1, (opkg_cmd_fun_t) opkg_remove_cmd,
1276 PFM_DESCRIPTION | PFM_SOURCE},
1277 {"configure", 0, (opkg_cmd_fun_t) opkg_configure_cmd,
1278 PFM_DESCRIPTION | PFM_SOURCE},
1279 {"files", 1, (opkg_cmd_fun_t) opkg_files_cmd,
1280 PFM_DESCRIPTION | PFM_SOURCE},
1281 {"search", 1, (opkg_cmd_fun_t) opkg_search_cmd,
1282 PFM_DESCRIPTION | PFM_SOURCE},
1283 {"find", 1, (opkg_cmd_fun_t) opkg_find_cmd, PFM_SOURCE},
1284 {"download", 1, (opkg_cmd_fun_t) opkg_download_cmd,
1285 PFM_DESCRIPTION | PFM_SOURCE},
1286 {"compare_versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd,
1287 PFM_DESCRIPTION | PFM_SOURCE},
1288 {"compare-versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd,
1289 PFM_DESCRIPTION | PFM_SOURCE},
1290 {"print-architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1291 PFM_DESCRIPTION | PFM_SOURCE},
1292 {"print_architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1293 PFM_DESCRIPTION | PFM_SOURCE},
1294 {"print-installation-architecture", 0,
1295 (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1296 PFM_DESCRIPTION | PFM_SOURCE},
1297 {"print_installation_architecture", 0,
1298 (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1299 PFM_DESCRIPTION | PFM_SOURCE},
1300 {"depends", 1, (opkg_cmd_fun_t) opkg_depends_cmd,
1301 PFM_DESCRIPTION | PFM_SOURCE},
1302 {"whatdepends", 1, (opkg_cmd_fun_t) opkg_whatdepends_cmd,
1303 PFM_DESCRIPTION | PFM_SOURCE},
1304 {"whatdependsrec", 1, (opkg_cmd_fun_t) opkg_whatdepends_recursively_cmd,
1305 PFM_DESCRIPTION | PFM_SOURCE},
1306 {"whatrecommends", 1, (opkg_cmd_fun_t) opkg_whatrecommends_cmd,
1307 PFM_DESCRIPTION | PFM_SOURCE},
1308 {"whatsuggests", 1, (opkg_cmd_fun_t) opkg_whatsuggests_cmd,
1309 PFM_DESCRIPTION | PFM_SOURCE},
1310 {"whatprovides", 1, (opkg_cmd_fun_t) opkg_whatprovides_cmd,
1311 PFM_DESCRIPTION | PFM_SOURCE},
1312 {"whatreplaces", 1, (opkg_cmd_fun_t) opkg_whatreplaces_cmd,
1313 PFM_DESCRIPTION | PFM_SOURCE},
1314 {"whatconflicts", 1, (opkg_cmd_fun_t) opkg_whatconflicts_cmd,
1315 PFM_DESCRIPTION | PFM_SOURCE},
1318 opkg_cmd_t *opkg_cmd_find(const char *name)
1322 int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
1324 for (i = 0; i < num_cmds; i++) {
1326 if (strcmp(name, cmd->name) == 0)
1333 int opkg_cmd_exec(opkg_cmd_t * cmd, int argc, const char **argv)
1335 return (cmd->fun) (argc, argv);