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 printf("%s - %s", pkg->name, version);
51 printf(" - %lu", pkg->size);
53 printf(" - %s", pkg->description);
58 int opkg_state_changed;
60 static void write_status_files_if_changed(void)
62 if (opkg_state_changed && !conf->noaction) {
63 opkg_msg(INFO, "Writing status file.\n");
64 opkg_conf_write_status_files();
65 pkg_write_changed_filelists();
67 opkg_msg(DEBUG, "Nothing to be done.\n");
71 static void sigint_handler(int sig)
74 opkg_msg(NOTICE, "Interrupted. Writing out status database.\n");
75 write_status_files_if_changed();
79 static int opkg_update_cmd(int argc, char **argv)
86 pkg_src_list_elt_t *iter;
89 sprintf_alloc(&lists_dir, "%s",
90 conf->restrict_to_default_dest ? conf->default_dest->
91 lists_dir : conf->lists_dir);
93 if (!file_is_dir(lists_dir)) {
94 if (file_exists(lists_dir)) {
95 opkg_msg(ERROR, "%s exists, but is not a directory.\n",
100 err = file_mkdir_hier(lists_dir, 0755);
109 sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
110 if (mkdtemp(tmp) == NULL) {
111 opkg_perror(ERROR, "Failed to make temp dir %s", conf->tmp_dir);
115 for (iter = void_list_first(&conf->pkg_src_list); iter;
116 iter = void_list_next(&conf->pkg_src_list, iter)) {
117 char *url, *list_file_name;
119 src = (pkg_src_t *) iter->data;
121 if (src->extra_data && strcmp(src->extra_data, "__dummy__ "))
124 if (src->extra_data) /* debian style? */
125 sprintf_alloc(&url, "%s/%s/%s", src->value,
127 src->gzip ? "Packages.gz" : "Packages");
129 sprintf_alloc(&url, "%s/%s", src->value,
130 src->gzip ? "Packages.gz" : "Packages");
132 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
133 pkglist_dl_error = 0;
134 if (opkg_download(url, list_file_name, NULL, NULL, 0)) {
136 pkglist_dl_error = 1;
138 "*** Failed to download the package list from %s\n\n",
142 "Updated list of available packages in %s\n",
146 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN)
147 if (pkglist_dl_error == 0 && conf->check_signature) {
148 /* download detached signitures to verify the package lists */
149 /* get the url for the sig file */
150 if (src->extra_data) /* debian style? */
151 sprintf_alloc(&url, "%s/%s/%s", src->value,
152 src->extra_data, "Packages.sig");
154 sprintf_alloc(&url, "%s/%s", src->value,
157 /* create temporary file for it */
160 /* Put the signature in the right place */
161 sprintf_alloc(&tmp_file_name, "%s/%s.sig", lists_dir,
164 err = opkg_download(url, tmp_file_name, NULL, NULL, 0);
168 "Signature file download failed.\n");
171 opkg_verify_file(list_file_name,
175 "Signature check passed.\n");
178 "Signature check failed.\n");
180 if (err && !conf->force_signature) {
181 /* The signature was wrong so delete it */
183 "Remove wrong Signature file.\n");
184 unlink(tmp_file_name);
185 unlink(list_file_name);
187 /* We shouldn't unlink the signature ! */
188 // unlink (tmp_file_name);
195 free(list_file_name);
204 struct opkg_intercept {
209 typedef struct opkg_intercept *opkg_intercept_t;
211 static opkg_intercept_t opkg_prep_intercepts(void)
213 opkg_intercept_t ctx;
216 ctx = xcalloc(1, sizeof(*ctx));
217 ctx->oldpath = xstrdup(getenv("PATH"));
218 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
219 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX",
222 if (mkdtemp(ctx->statedir) == NULL) {
223 opkg_perror(ERROR, "Failed to make temp dir %s", ctx->statedir);
231 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
232 setenv("PATH", newpath, 1);
238 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
243 setenv("PATH", ctx->oldpath, 1);
246 dir = opendir(ctx->statedir);
249 while (de = readdir(dir), de != NULL) {
252 if (de->d_name[0] == '.')
255 sprintf_alloc(&path, "%s/%s", ctx->statedir,
257 if (access(path, X_OK) == 0) {
258 const char *argv[] = { "sh", "-c", path, NULL };
265 opkg_perror(ERROR, "Failed to open dir %s", ctx->statedir);
274 /* For package pkg do the following: If it is already visited, return. If not,
275 add it in visited list and recurse to its deps. Finally, add it to ordered
277 pkg_vec all contains all available packages in repos.
278 pkg_vec visited contains packages already visited by this function, and is
279 used to end recursion and avoid an infinite loop on graph cycles.
280 pkg_vec ordered will finally contain the ordered set of packages.
283 opkg_recurse_pkgs_in_order(pkg_t * pkg, pkg_vec_t * all,
284 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 count = pkg->pre_depends_count + pkg->depends_count +
315 pkg->recommends_count + pkg->suggests_count;
317 opkg_msg(DEBUG, "pkg %s.\n", pkg->name);
319 /* Iterate over all the dependencies of pkg. For each one, find a package
320 that is either installed or unpacked and satisfies this dependency.
321 (there should only be one such package per dependency installed or
322 unpacked). Then recurse to the dependency package */
323 for (j = 0; j < count; j++) {
324 compound_depend = &pkg->depends[j];
325 possible_satisfiers = compound_depend->possibilities;
326 for (k = 0; k < compound_depend->possibility_count; k++) {
327 abpkg = possible_satisfiers[k]->pkg;
328 dependents = abpkg->provided_by->pkgs;
330 if (dependents != NULL)
331 while (l < abpkg->provided_by->len
332 && dependents[l] != NULL) {
334 "Descending on pkg %s.\n",
335 dependents[l]->name);
337 /* find whether dependent l is installed or unpacked,
338 * and then find which package in the list satisfies it */
339 for (m = 0; m < all->len; m++) {
341 if (dep->state_status !=
347 opkg_recurse_pkgs_in_order
351 /* Stop the outer loop */
355 /* break from the inner loop */
364 /* When all recursions from this node down, are over, and all
365 dependencies have been added in proper order in the ordered array, add
366 also the package pkg to ordered array */
367 pkg_vec_insert(ordered, pkg);
373 static int opkg_configure_packages(char *pkg_name)
375 pkg_vec_t *all, *ordered, *visited;
381 opkg_msg(INFO, "Configuring unpacked packages.\n");
383 all = pkg_vec_alloc();
385 pkg_hash_fetch_available(all);
387 /* Reorder pkgs in order to be configured according to the Depends: tag
389 opkg_msg(INFO, "Reordering packages before configuring them...\n");
390 ordered = pkg_vec_alloc();
391 visited = pkg_vec_alloc();
392 for (i = 0; i < all->len; i++) {
394 opkg_recurse_pkgs_in_order(pkg, all, visited, ordered);
397 ic = opkg_prep_intercepts();
403 for (i = 0; i < ordered->len; i++) {
404 pkg = ordered->pkgs[i];
406 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
409 if (pkg->state_status == SS_UNPACKED) {
410 opkg_msg(NOTICE, "Configuring %s.\n", pkg->name);
411 r = opkg_configure(pkg);
413 pkg->state_status = SS_INSTALLED;
414 pkg->parent->state_status = SS_INSTALLED;
415 pkg->state_flag &= ~SF_PREFER;
416 opkg_state_changed++;
423 if (opkg_finalize_intercepts(ic))
428 pkg_vec_free(ordered);
429 pkg_vec_free(visited);
434 static int opkg_remove_cmd(int argc, char **argv);
436 static int opkg_install_cmd(int argc, char **argv)
442 if (conf->force_reinstall) {
443 int saved_force_depends = conf->force_depends;
444 conf->force_depends = 1;
445 (void)opkg_remove_cmd(argc, argv);
446 conf->force_depends = saved_force_depends;
447 conf->force_reinstall = 0;
450 signal(SIGINT, sigint_handler);
453 * Now scan through package names and install
455 for (i = 0; i < argc; i++) {
458 opkg_msg(DEBUG2, "%s\n", arg);
459 if (opkg_prepare_url_for_install(arg, &argv[i]))
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->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;
573 available = pkg_vec_alloc();
574 pkg_hash_fetch_available(available);
575 pkg_vec_sort(available, pkg_compare_names);
576 for (i = 0; i < available->len; i++) {
577 pkg = available->pkgs[i];
578 /* if we have package name or pattern and pkg does not match, then skip it */
579 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase) &&
580 (!use_desc || !pkg->description
581 || fnmatch(pkg_name, pkg->description, conf->nocase)))
585 pkg_vec_free(available);
590 static int opkg_list_cmd(int argc, char **argv)
592 return opkg_list_find_cmd(argc, argv, 0);
595 static int opkg_find_cmd(int argc, char **argv)
597 return opkg_list_find_cmd(argc, argv, 1);
600 static int opkg_list_installed_cmd(int argc, char **argv)
603 pkg_vec_t *available;
605 char *pkg_name = NULL;
610 available = pkg_vec_alloc();
611 pkg_hash_fetch_all_installed(available);
612 pkg_vec_sort(available, pkg_compare_names);
613 for (i = 0; i < available->len; i++) {
614 pkg = available->pkgs[i];
615 /* if we have package name or pattern and pkg does not match, then skip it */
616 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
621 pkg_vec_free(available);
626 static int opkg_list_changed_conffiles_cmd(int argc, char **argv)
629 pkg_vec_t *available;
631 char *pkg_name = NULL;
632 conffile_list_elt_t *iter;
638 available = pkg_vec_alloc();
639 pkg_hash_fetch_all_installed(available);
640 pkg_vec_sort(available, pkg_compare_names);
641 for (i = 0; i < available->len; i++) {
642 pkg = available->pkgs[i];
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 (nv_pair_list_empty(&pkg->conffiles))
648 for (iter = nv_pair_list_first(&pkg->conffiles); iter;
649 iter = nv_pair_list_next(&pkg->conffiles, 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 = list_entry(node, pkg_t, list);
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;
695 available = pkg_vec_alloc();
697 pkg_hash_fetch_all_installed(available);
699 pkg_hash_fetch_available(available);
701 for (i = 0; i < available->len; i++) {
702 pkg = available->pkgs[i];
703 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) {
707 pkg_formatted_info(stdout, pkg);
709 if (conf->verbosity >= NOTICE) {
710 conffile_list_elt_t *iter;
711 for (iter = nv_pair_list_first(&pkg->conffiles); iter;
712 iter = nv_pair_list_next(&pkg->conffiles, iter)) {
713 conffile_t *cf = (conffile_t *) iter->data;
714 int modified = conffile_has_been_modified(cf);
717 "conffile=%s md5sum=%s modified=%d.\n",
718 cf->name, cf->value, modified);
722 pkg_vec_free(available);
727 static int opkg_info_cmd(int argc, char **argv)
729 return opkg_info_status_cmd(argc, argv, 0);
732 static int opkg_status_cmd(int argc, char **argv)
734 return opkg_info_status_cmd(argc, argv, 1);
737 static int opkg_configure_cmd(int argc, char **argv)
740 char *pkg_name = NULL;
745 err = opkg_configure_packages(pkg_name);
747 write_status_files_if_changed();
752 static int opkg_remove_cmd(int argc, char **argv)
754 int i, a, done, err = 0;
756 pkg_t *pkg_to_remove;
757 pkg_vec_t *available;
761 signal(SIGINT, sigint_handler);
763 pkg_info_preinstall_check();
765 available = pkg_vec_alloc();
766 pkg_hash_fetch_all_installed(available);
768 for (i = 0; i < argc; i++) {
769 for (a = 0; a < available->len; a++) {
770 pkg = available->pkgs[a];
771 if (fnmatch(argv[i], pkg->name, conf->nocase)) {
774 if (conf->restrict_to_default_dest) {
776 pkg_hash_fetch_installed_by_name_dest(pkg->
782 pkg_hash_fetch_installed_by_name(pkg->name);
785 if (pkg_to_remove == NULL) {
787 "Package %s is not installed.\n",
791 if (pkg->state_status == SS_NOT_INSTALLED) {
792 opkg_msg(ERROR, "Package %s not installed.\n",
797 if (opkg_remove_pkg(pkg_to_remove, 0))
804 pkg_vec_free(available);
807 opkg_msg(NOTICE, "No packages removed.\n");
809 write_status_files_if_changed();
813 static int opkg_flag_cmd(int argc, char **argv)
817 const char *flags = argv[0];
819 signal(SIGINT, sigint_handler);
821 for (i = 1; i < argc; i++) {
822 if (conf->restrict_to_default_dest) {
823 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
827 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
831 opkg_msg(ERROR, "Package %s is not installed.\n",
835 if ((strcmp(flags, "hold") == 0)
836 || (strcmp(flags, "noprune") == 0)
837 || (strcmp(flags, "user") == 0)
838 || (strcmp(flags, "ok") == 0)) {
839 pkg->state_flag = pkg_state_flag_from_str(flags);
843 * Useful if a package is installed in an offline_root, and
844 * should be configured by opkg-cl configure at a later date.
846 if ((strcmp(flags, "installed") == 0)
847 || (strcmp(flags, "unpacked") == 0)) {
848 pkg->state_status = pkg_state_status_from_str(flags);
851 opkg_state_changed++;
852 opkg_msg(NOTICE, "Setting flags for package %s to %s.\n",
856 write_status_files_if_changed();
860 static int opkg_files_cmd(int argc, char **argv)
864 str_list_elt_t *iter;
871 pkg = pkg_hash_fetch_installed_by_name(argv[0]);
873 opkg_msg(ERROR, "Package %s not installed.\n", argv[0]);
877 files = pkg_get_installed_files(pkg);
878 pkg_version = pkg_version_str_alloc(pkg);
881 ("Package %s (%s) is installed on %s and has the following files:\n",
882 pkg->name, pkg_version, pkg->dest->name);
884 for (iter = str_list_first(files); iter;
885 iter = str_list_next(files, iter))
886 printf("%s\n", (char *)iter->data);
889 pkg_free_installed_files(pkg);
894 static int opkg_depends_cmd(int argc, char **argv)
898 pkg_vec_t *available_pkgs;
899 compound_depend_t *cdep;
903 pkg_info_preinstall_check();
905 available_pkgs = pkg_vec_alloc();
907 pkg_hash_fetch_available(available_pkgs);
909 pkg_hash_fetch_all_installed(available_pkgs);
911 for (i = 0; i < argc; i++) {
912 for (j = 0; j < available_pkgs->len; j++) {
913 pkg = available_pkgs->pkgs[j];
915 if (fnmatch(argv[i], pkg->name, conf->nocase) != 0)
918 depends_count = pkg->depends_count +
919 pkg->pre_depends_count +
920 pkg->recommends_count + pkg->suggests_count;
922 opkg_msg(NOTICE, "%s depends on:\n", pkg->name);
924 for (k = 0; k < depends_count; k++) {
925 cdep = &pkg->depends[k];
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 int provides_count = pkg->provides_count;
945 abstract_pkg_t **provides = pkg->provides;
947 pkg->parent->state_flag |= SF_MARKED;
948 for (i = 0; i < provides_count; i++) {
949 provides[i]->state_flag |= SF_MARKED;
954 enum what_field_type {
964 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive,
965 int argc, char **argv)
967 depend_t *possibility;
968 compound_depend_t *cdep;
969 pkg_vec_t *available_pkgs;
973 const char *rel_str = NULL;
976 switch (what_field_type) {
978 rel_str = "depends on";
981 rel_str = "conflicts with";
984 rel_str = "suggests";
987 rel_str = "recommends";
993 available_pkgs = pkg_vec_alloc();
996 pkg_hash_fetch_available(available_pkgs);
998 pkg_hash_fetch_all_installed(available_pkgs);
1000 /* mark the root set */
1001 pkg_vec_clear_marks(available_pkgs);
1002 opkg_msg(NOTICE, "Root set:\n");
1003 for (i = 0; i < argc; i++)
1004 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
1006 for (i = 0; i < available_pkgs->len; i++) {
1007 pkg = available_pkgs->pkgs[i];
1008 if (pkg->state_flag & SF_MARKED) {
1009 /* mark the parent (abstract) package */
1010 pkg_mark_provides(pkg);
1011 opkg_msg(NOTICE, " %s\n", pkg->name);
1015 opkg_msg(NOTICE, "What %s root set\n", rel_str);
1019 for (j = 0; j < available_pkgs->len; j++) {
1021 pkg = available_pkgs->pkgs[j];
1022 count = ((what_field_type == CONFLICTS)
1023 ? pkg->conflicts_count
1024 : pkg->pre_depends_count +
1025 pkg->depends_count +
1026 pkg->recommends_count + pkg->suggests_count);
1028 /* skip this package if it is already marked */
1029 if (pkg->parent->state_flag & SF_MARKED)
1032 for (k = 0; k < count; k++) {
1033 cdep = (what_field_type == CONFLICTS)
1034 ? &pkg->conflicts[k]
1037 if (what_field_type != cdep->type)
1040 for (l = 0; l < cdep->possibility_count; l++) {
1041 possibility = cdep->possibilities[l];
1043 if ((possibility->pkg->state_flag
1048 /* mark the depending package so we
1049 * won't visit it again */
1050 pkg->state_flag |= SF_MARKED;
1051 pkg_mark_provides(pkg);
1054 ver = pkg_version_str_alloc(pkg);
1055 opkg_msg(NOTICE, "\t%s %s\t%s %s",
1059 possibility->pkg->name);
1061 if (possibility->version) {
1062 opkg_msg(NOTICE, " (%s%s)",
1066 possibility->version);
1068 if (!pkg_dependence_satisfiable
1072 opkg_message(NOTICE, "\n");
1079 } while (changed && recursive);
1081 pkg_vec_free(available_pkgs);
1086 static int opkg_whatdepends_recursively_cmd(int argc, char **argv)
1088 return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv);
1091 static int opkg_whatdepends_cmd(int argc, char **argv)
1093 return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv);
1096 static int opkg_whatsuggests_cmd(int argc, char **argv)
1098 return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv);
1101 static int opkg_whatrecommends_cmd(int argc, char **argv)
1103 return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv);
1106 static int opkg_whatconflicts_cmd(int argc, char **argv)
1108 return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv);
1112 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc,
1117 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1118 const char *rel_str =
1119 (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1122 pkg_info_preinstall_check();
1124 if (conf->query_all)
1125 pkg_hash_fetch_available(available_pkgs);
1127 pkg_hash_fetch_all_installed(available_pkgs);
1128 for (i = 0; i < argc; i++) {
1129 const char *target = argv[i];
1132 opkg_msg(NOTICE, "What %s %s\n", rel_str, target);
1133 for (j = 0; j < available_pkgs->len; j++) {
1134 pkg_t *pkg = available_pkgs->pkgs[j];
1138 WHATPROVIDES) ? pkg->provides_count : pkg->
1140 for (k = 0; k < count; k++) {
1141 abstract_pkg_t *apkg =
1142 ((what_field_type == WHATPROVIDES)
1144 : pkg->replaces[k]);
1146 (target, apkg->name,
1147 conf->nocase) == 0) {
1148 opkg_msg(NOTICE, " %s",
1151 nocase ? strcasecmp(target,
1160 opkg_message(NOTICE, "\n");
1165 pkg_vec_free(available_pkgs);
1170 static int opkg_whatprovides_cmd(int argc, char **argv)
1172 return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv);
1175 static int opkg_whatreplaces_cmd(int argc, char **argv)
1177 return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv);
1180 static int opkg_search_cmd(int argc, char **argv)
1184 pkg_vec_t *installed;
1186 str_list_t *installed_files;
1187 str_list_elt_t *iter;
1188 char *installed_file;
1194 installed = pkg_vec_alloc();
1195 pkg_hash_fetch_all_installed(installed);
1196 pkg_vec_sort(installed, pkg_compare_names);
1198 for (i = 0; i < installed->len; i++) {
1199 pkg = installed->pkgs[i];
1201 installed_files = pkg_get_installed_files(pkg);
1203 for (iter = str_list_first(installed_files); iter;
1204 iter = str_list_next(installed_files, iter)) {
1205 installed_file = (char *)iter->data;
1206 if (fnmatch(argv[0], installed_file, conf->nocase) == 0)
1210 pkg_free_installed_files(pkg);
1213 pkg_vec_free(installed);
1218 static int opkg_compare_versions_cmd(int argc, char **argv)
1221 /* this is a bit gross */
1223 parse_version(&p1, argv[0]);
1224 parse_version(&p2, argv[2]);
1225 return pkg_version_satisfied(&p1, &p2, argv[1]);
1228 "opkg compare_versions <v1> <op> <v2>\n"
1229 "<op> is one of <= >= << >> =\n");
1234 static int opkg_print_architecture_cmd(int argc, char **argv)
1236 nv_pair_list_elt_t *l;
1238 list_for_each_entry(l, &conf->arch_list.head, node) {
1239 nv_pair_t *nv = (nv_pair_t *) l->data;
1240 printf("arch %s %s\n", nv->name, nv->value);
1245 /* XXX: CLEANUP: The usage strings should be incorporated into this
1246 array for easier maintenance */
1247 static opkg_cmd_t cmds[] = {
1248 {"update", 0, (opkg_cmd_fun_t) opkg_update_cmd,
1249 PFM_DESCRIPTION | PFM_SOURCE},
1250 {"upgrade", 1, (opkg_cmd_fun_t) opkg_upgrade_cmd,
1251 PFM_DESCRIPTION | PFM_SOURCE},
1252 {"list", 0, (opkg_cmd_fun_t) opkg_list_cmd, PFM_SOURCE},
1253 {"list_installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1255 {"list-installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd,
1257 {"list_upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1259 {"list-upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd,
1261 {"list_changed_conffiles", 0,
1262 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1263 {"list-changed-conffiles", 0,
1264 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1265 {"info", 0, (opkg_cmd_fun_t) opkg_info_cmd, 0},
1266 {"flag", 1, (opkg_cmd_fun_t) opkg_flag_cmd,
1267 PFM_DESCRIPTION | PFM_SOURCE},
1268 {"status", 0, (opkg_cmd_fun_t) opkg_status_cmd,
1269 PFM_DESCRIPTION | PFM_SOURCE},
1270 {"install", 1, (opkg_cmd_fun_t) opkg_install_cmd,
1271 PFM_DESCRIPTION | PFM_SOURCE},
1272 {"remove", 1, (opkg_cmd_fun_t) opkg_remove_cmd,
1273 PFM_DESCRIPTION | PFM_SOURCE},
1274 {"configure", 0, (opkg_cmd_fun_t) opkg_configure_cmd,
1275 PFM_DESCRIPTION | PFM_SOURCE},
1276 {"files", 1, (opkg_cmd_fun_t) opkg_files_cmd,
1277 PFM_DESCRIPTION | PFM_SOURCE},
1278 {"search", 1, (opkg_cmd_fun_t) opkg_search_cmd,
1279 PFM_DESCRIPTION | PFM_SOURCE},
1280 {"find", 1, (opkg_cmd_fun_t) opkg_find_cmd, PFM_SOURCE},
1281 {"download", 1, (opkg_cmd_fun_t) opkg_download_cmd,
1282 PFM_DESCRIPTION | PFM_SOURCE},
1283 {"compare_versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd,
1284 PFM_DESCRIPTION | PFM_SOURCE},
1285 {"compare-versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd,
1286 PFM_DESCRIPTION | PFM_SOURCE},
1287 {"print-architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1288 PFM_DESCRIPTION | PFM_SOURCE},
1289 {"print_architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd,
1290 PFM_DESCRIPTION | PFM_SOURCE},
1291 {"print-installation-architecture", 0,
1292 (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 {"depends", 1, (opkg_cmd_fun_t) opkg_depends_cmd,
1298 PFM_DESCRIPTION | PFM_SOURCE},
1299 {"whatdepends", 1, (opkg_cmd_fun_t) opkg_whatdepends_cmd,
1300 PFM_DESCRIPTION | PFM_SOURCE},
1301 {"whatdependsrec", 1, (opkg_cmd_fun_t) opkg_whatdepends_recursively_cmd,
1302 PFM_DESCRIPTION | PFM_SOURCE},
1303 {"whatrecommends", 1, (opkg_cmd_fun_t) opkg_whatrecommends_cmd,
1304 PFM_DESCRIPTION | PFM_SOURCE},
1305 {"whatsuggests", 1, (opkg_cmd_fun_t) opkg_whatsuggests_cmd,
1306 PFM_DESCRIPTION | PFM_SOURCE},
1307 {"whatprovides", 1, (opkg_cmd_fun_t) opkg_whatprovides_cmd,
1308 PFM_DESCRIPTION | PFM_SOURCE},
1309 {"whatreplaces", 1, (opkg_cmd_fun_t) opkg_whatreplaces_cmd,
1310 PFM_DESCRIPTION | PFM_SOURCE},
1311 {"whatconflicts", 1, (opkg_cmd_fun_t) opkg_whatconflicts_cmd,
1312 PFM_DESCRIPTION | PFM_SOURCE},
1315 opkg_cmd_t *opkg_cmd_find(const char *name)
1319 int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
1321 for (i = 0; i < num_cmds; i++) {
1323 if (strcmp(name, cmd->name) == 0)
1330 int opkg_cmd_exec(opkg_cmd_t * cmd, int argc, const char **argv)
1332 return (cmd->fun) (argc, argv);