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"
49 char *version = pkg_version_str_alloc(pkg);
50 printf("%s - %s", pkg->name, version);
52 printf(" - %lu", pkg->size);
54 printf(" - %s", pkg->description);
59 int opkg_state_changed;
62 write_status_files_if_changed(void)
64 if (opkg_state_changed && !conf->noaction) {
65 opkg_msg(INFO, "Writing status file.\n");
66 opkg_conf_write_status_files();
67 pkg_write_changed_filelists();
69 opkg_msg(DEBUG, "Nothing to be done.\n");
74 sigint_handler(int sig)
77 opkg_msg(NOTICE, "Interrupted. Writing out status database.\n");
78 write_status_files_if_changed();
83 opkg_update_cmd(int argc, char **argv)
90 pkg_src_list_elt_t *iter;
94 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
96 if (! file_is_dir(lists_dir)) {
97 if (file_exists(lists_dir)) {
98 opkg_msg(ERROR, "%s exists, but is not a directory.\n",
103 err = file_mkdir_hier(lists_dir, 0755);
112 sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
113 if (mkdtemp (tmp) == NULL) {
114 opkg_perror(ERROR, "Failed to make temp dir %s", conf->tmp_dir);
119 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
120 char *url, *list_file_name;
122 src = (pkg_src_t *)iter->data;
124 if (src->extra_data && strcmp(src->extra_data, "__dummy__ "))
127 if (src->extra_data) /* debian style? */
128 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
129 src->gzip ? "Packages.gz" : "Packages");
131 sprintf_alloc(&url, "%s/%s", src->value, 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;
138 opkg_msg(NOTICE, "*** Failed to download the package list from %s\n\n",
141 opkg_msg(NOTICE, "Updated list of available packages in %s\n",
145 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN)
146 if (pkglist_dl_error == 0 && conf->check_signature) {
147 /* download detached signitures to verify the package lists */
148 /* get the url for the sig file */
149 if (src->extra_data) /* debian style? */
150 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
153 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
155 /* create temporary file for it */
158 /* Put the signature in the right place */
159 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
161 err = opkg_download(url, tmp_file_name, NULL, NULL, 0);
164 opkg_msg(NOTICE, "Signature file download failed.\n");
166 err = opkg_verify_file (list_file_name, tmp_file_name);
168 opkg_msg(NOTICE, "Signature check passed.\n");
170 opkg_msg(NOTICE, "Signature check failed.\n");
172 if (err && !conf->force_signature) {
173 /* The signature was wrong so delete it */
174 opkg_msg(NOTICE, "Remove wrong Signature file.\n");
175 unlink (tmp_file_name);
176 unlink (list_file_name);
178 /* We shouldn't unlink the signature ! */
179 // unlink (tmp_file_name);
180 free (tmp_file_name);
186 free(list_file_name);
196 struct opkg_intercept
202 typedef struct opkg_intercept *opkg_intercept_t;
204 static opkg_intercept_t
205 opkg_prep_intercepts(void)
207 opkg_intercept_t ctx;
210 ctx = xcalloc(1, sizeof (*ctx));
211 ctx->oldpath = xstrdup(getenv("PATH"));
212 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
213 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX", conf->tmp_dir);
215 if (mkdtemp(ctx->statedir) == NULL) {
216 opkg_perror(ERROR,"Failed to make temp dir %s", ctx->statedir);
224 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
225 setenv("PATH", newpath, 1);
232 opkg_finalize_intercepts(opkg_intercept_t ctx)
237 setenv ("PATH", ctx->oldpath, 1);
240 dir = opendir (ctx->statedir);
243 while (de = readdir (dir), de != NULL) {
246 if (de->d_name[0] == '.')
249 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
250 if (access (path, X_OK) == 0) {
251 const char *argv[] = {"sh", "-c", path, NULL};
258 opkg_perror(ERROR, "Failed to open dir %s", ctx->statedir);
261 free (ctx->statedir);
267 /* For package pkg do the following: If it is already visited, return. If not,
268 add it in visited list and recurse to its deps. Finally, add it to ordered
270 pkg_vec all contains all available packages in repos.
271 pkg_vec visited contains packages already visited by this function, and is
272 used to end recursion and avoid an infinite loop on graph cycles.
273 pkg_vec ordered will finally contain the ordered set of packages.
276 opkg_recurse_pkgs_in_order(pkg_t *pkg, pkg_vec_t *all,
277 pkg_vec_t *visited, pkg_vec_t *ordered)
282 compound_depend_t * compound_depend;
283 depend_t ** possible_satisfiers;
284 abstract_pkg_t *abpkg;
285 abstract_pkg_t **dependents;
287 /* If it's just an available package, that is, not installed and not even
289 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
290 would do here. However, if there is an intermediate node (pkg) that is
291 configured and installed between two unpacked packages, the latter
292 won't be properly reordered, unless all installed/unpacked pkgs are
294 if (pkg->state_status == SS_NOT_INSTALLED)
297 /* If the package has already been visited (by this function), skip it */
298 for(j = 0; j < visited->len; j++)
299 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
300 opkg_msg(DEBUG, "pkg %s already visited, skipping.\n", pkg->name);
304 pkg_vec_insert(visited, pkg);
306 count = pkg->pre_depends_count + pkg->depends_count + \
307 pkg->recommends_count + pkg->suggests_count;
309 opkg_msg(DEBUG, "pkg %s.\n", pkg->name);
311 /* Iterate over all the dependencies of pkg. For each one, find a package
312 that is either installed or unpacked and satisfies this dependency.
313 (there should only be one such package per dependency installed or
314 unpacked). Then recurse to the dependency package */
315 for (j=0; j < count ; j++) {
316 compound_depend = &pkg->depends[j];
317 possible_satisfiers = compound_depend->possibilities;
318 for (k=0; k < compound_depend->possibility_count ; k++) {
319 abpkg = possible_satisfiers[k]->pkg;
320 dependents = abpkg->provided_by->pkgs;
322 if (dependents != NULL)
323 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
324 opkg_msg(DEBUG, "Descending on pkg %s.\n",
325 dependents [l]->name);
327 /* find whether dependent l is installed or unpacked,
328 * and then find which package in the list satisfies it */
329 for(m = 0; m < all->len; m++) {
331 if ( dep->state_status != SS_NOT_INSTALLED)
332 if ( ! strcmp(dep->name, dependents[l]->name)) {
333 opkg_recurse_pkgs_in_order(dep, all,
335 /* Stop the outer loop */
336 l = abpkg->provided_by->len;
337 /* break from the inner loop */
346 /* When all recursions from this node down, are over, and all
347 dependencies have been added in proper order in the ordered array, add
348 also the package pkg to ordered array */
349 pkg_vec_insert(ordered, pkg);
356 opkg_configure_packages(char *pkg_name)
358 pkg_vec_t *all, *ordered, *visited;
364 opkg_msg(INFO, "Configuring unpacked packages.\n");
366 all = pkg_vec_alloc();
368 pkg_hash_fetch_available(all);
370 /* Reorder pkgs in order to be configured according to the Depends: tag
372 opkg_msg(INFO, "Reordering packages before configuring them...\n");
373 ordered = pkg_vec_alloc();
374 visited = pkg_vec_alloc();
375 for(i = 0; i < all->len; i++) {
377 opkg_recurse_pkgs_in_order(pkg, all, visited, ordered);
380 ic = opkg_prep_intercepts();
386 for(i = 0; i < ordered->len; i++) {
387 pkg = ordered->pkgs[i];
389 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
392 if (pkg->state_status == SS_UNPACKED) {
393 opkg_msg(NOTICE, "Configuring %s.\n", pkg->name);
394 r = opkg_configure(pkg);
396 pkg->state_status = SS_INSTALLED;
397 pkg->parent->state_status = SS_INSTALLED;
398 pkg->state_flag &= ~SF_PREFER;
399 opkg_state_changed++;
406 if (opkg_finalize_intercepts (ic))
411 pkg_vec_free(ordered);
412 pkg_vec_free(visited);
418 opkg_remove_cmd(int argc, char **argv);
421 opkg_install_cmd(int argc, char **argv)
427 if (conf->force_reinstall) {
428 int saved_force_depends = conf->force_depends;
429 conf->force_depends = 1;
430 (void)opkg_remove_cmd(argc, argv);
431 conf->force_depends = saved_force_depends;
432 conf->force_reinstall = 0;
435 signal(SIGINT, sigint_handler);
438 * Now scan through package names and install
440 for (i=0; i < argc; i++) {
443 opkg_msg(DEBUG2, "%s\n", arg);
444 if (opkg_prepare_url_for_install(arg, &argv[i]))
447 pkg_info_preinstall_check();
449 for (i=0; i < argc; i++) {
451 if (opkg_install_by_name(arg)) {
452 opkg_msg(ERROR, "Cannot install package %s.\n", arg);
457 if (opkg_configure_packages(NULL))
460 write_status_files_if_changed();
466 opkg_upgrade_cmd(int argc, char **argv)
472 signal(SIGINT, sigint_handler);
475 for (i=0; i < argc; i++) {
478 if (opkg_prepare_url_for_install(arg, &arg))
481 pkg_info_preinstall_check();
483 for (i=0; i < argc; i++) {
485 if (conf->restrict_to_default_dest) {
486 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
489 opkg_msg(NOTICE, "Package %s not installed in %s.\n",
490 argv[i], conf->default_dest->name);
494 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
497 if (opkg_upgrade_pkg(pkg))
500 if (opkg_install_by_name(arg))
506 if (opkg_configure_packages(NULL))
509 write_status_files_if_changed();
515 opkg_download_cmd(int argc, char **argv)
521 pkg_info_preinstall_check();
522 for (i = 0; i < argc; i++) {
525 pkg = pkg_hash_fetch_best_installation_candidate_by_name(arg);
527 opkg_msg(ERROR, "Cannot find package %s.\n", arg);
531 if (opkg_download_pkg(pkg, "."))
535 opkg_msg(ERROR, "Failed to download %s.\n", pkg->name);
537 opkg_msg(NOTICE, "Downloaded %s as %s.\n",
538 pkg->name, pkg->local_filename);
547 opkg_list_find_cmd(int argc, char **argv, int use_desc)
550 pkg_vec_t *available;
552 char *pkg_name = NULL;
557 available = pkg_vec_alloc();
558 pkg_hash_fetch_available(available);
559 pkg_vec_sort(available, pkg_compare_names);
560 for (i=0; i < available->len; i++) {
561 pkg = available->pkgs[i];
562 /* if we have package name or pattern and pkg does not match, then skip it */
563 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase) &&
564 (!use_desc || !pkg->description || fnmatch(pkg_name, pkg->description, conf->nocase)))
568 pkg_vec_free(available);
574 opkg_list_cmd(int argc, char **argv)
576 return opkg_list_find_cmd(argc, argv, 0);
580 opkg_find_cmd(int argc, char **argv)
582 return opkg_list_find_cmd(argc, argv, 1);
587 opkg_list_installed_cmd(int argc, char **argv)
590 pkg_vec_t *available;
592 char *pkg_name = NULL;
597 available = pkg_vec_alloc();
598 pkg_hash_fetch_all_installed(available);
599 pkg_vec_sort(available, pkg_compare_names);
600 for (i=0; i < available->len; i++) {
601 pkg = available->pkgs[i];
602 /* if we have package name or pattern and pkg does not match, then skip it */
603 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
608 pkg_vec_free(available);
614 opkg_list_changed_conffiles_cmd(int argc, char **argv)
617 pkg_vec_t *available;
619 char *pkg_name = NULL;
620 conffile_list_elt_t *iter;
626 available = pkg_vec_alloc();
627 pkg_hash_fetch_all_installed(available);
628 pkg_vec_sort(available, pkg_compare_names);
629 for (i=0; i < available->len; i++) {
630 pkg = available->pkgs[i];
631 /* if we have package name or pattern and pkg does not match, then skip it */
632 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase))
634 if (nv_pair_list_empty(&pkg->conffiles))
636 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
637 cf = (conffile_t *)iter->data;
638 if (cf->name && cf->value && conffile_has_been_modified(cf))
639 printf("%s\n", cf->name);
642 pkg_vec_free(available);
647 opkg_list_upgradable_cmd(int argc, char **argv)
649 struct active_list *head = prepare_upgrade_list();
650 struct active_list *node=NULL;
651 pkg_t *_old_pkg, *_new_pkg;
653 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
654 _old_pkg = list_entry(node, pkg_t, list);
655 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg->name);
656 if (_new_pkg == NULL)
658 old_v = pkg_version_str_alloc(_old_pkg);
659 new_v = pkg_version_str_alloc(_new_pkg);
660 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
664 active_list_head_delete(head);
669 opkg_info_status_cmd(int argc, char **argv, int installed_only)
672 pkg_vec_t *available;
674 char *pkg_name = NULL;
680 available = pkg_vec_alloc();
682 pkg_hash_fetch_all_installed(available);
684 pkg_hash_fetch_available(available);
686 for (i=0; i < available->len; i++) {
687 pkg = available->pkgs[i];
688 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) {
692 pkg_formatted_info(stdout, pkg);
694 if (conf->verbosity >= NOTICE) {
695 conffile_list_elt_t *iter;
696 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
697 conffile_t *cf = (conffile_t *)iter->data;
698 int modified = conffile_has_been_modified(cf);
700 opkg_msg(INFO, "conffile=%s md5sum=%s modified=%d.\n",
701 cf->name, cf->value, modified);
705 pkg_vec_free(available);
711 opkg_info_cmd(int argc, char **argv)
713 return opkg_info_status_cmd(argc, argv, 0);
717 opkg_status_cmd(int argc, char **argv)
719 return opkg_info_status_cmd(argc, argv, 1);
723 opkg_configure_cmd(int argc, char **argv)
726 char *pkg_name = NULL;
731 err = opkg_configure_packages(pkg_name);
733 write_status_files_if_changed();
739 opkg_remove_cmd(int argc, char **argv)
741 int i, a, done, err = 0;
743 pkg_t *pkg_to_remove;
744 pkg_vec_t *available;
748 signal(SIGINT, sigint_handler);
750 pkg_info_preinstall_check();
752 available = pkg_vec_alloc();
753 pkg_hash_fetch_all_installed(available);
755 for (i=0; i<argc; i++) {
756 for (a=0; a<available->len; a++) {
757 pkg = available->pkgs[a];
758 if (fnmatch(argv[i], pkg->name, conf->nocase)) {
761 if (conf->restrict_to_default_dest) {
762 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(
766 pkg_to_remove = pkg_hash_fetch_installed_by_name(pkg->name);
769 if (pkg_to_remove == NULL) {
770 opkg_msg(ERROR, "Package %s is not installed.\n", pkg->name);
773 if (pkg->state_status == SS_NOT_INSTALLED) {
774 opkg_msg(ERROR, "Package %s not installed.\n", pkg->name);
778 if (opkg_remove_pkg(pkg_to_remove, 0))
785 pkg_vec_free(available);
788 opkg_msg(NOTICE, "No packages removed.\n");
790 write_status_files_if_changed();
795 opkg_flag_cmd(int argc, char **argv)
799 const char *flags = argv[0];
801 signal(SIGINT, sigint_handler);
803 for (i=1; i < argc; i++) {
804 if (conf->restrict_to_default_dest) {
805 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
808 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
812 opkg_msg(ERROR, "Package %s is not installed.\n", argv[i]);
815 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
816 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
817 pkg->state_flag = pkg_state_flag_from_str(flags);
821 * Useful if a package is installed in an offline_root, and
822 * should be configured by opkg-cl configure at a later date.
824 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
825 pkg->state_status = pkg_state_status_from_str(flags);
828 opkg_state_changed++;
829 opkg_msg(NOTICE, "Setting flags for package %s to %s.\n",
833 write_status_files_if_changed();
838 opkg_files_cmd(int argc, char **argv)
842 str_list_elt_t *iter;
849 pkg = pkg_hash_fetch_installed_by_name(argv[0]);
851 opkg_msg(ERROR, "Package %s not installed.\n", argv[0]);
855 files = pkg_get_installed_files(pkg);
856 pkg_version = pkg_version_str_alloc(pkg);
858 printf("Package %s (%s) is installed on %s and has the following files:\n",
859 pkg->name, pkg_version, pkg->dest->name);
861 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
862 printf("%s\n", (char *)iter->data);
865 pkg_free_installed_files(pkg);
871 opkg_depends_cmd(int argc, char **argv)
875 pkg_vec_t *available_pkgs;
876 compound_depend_t *cdep;
880 pkg_info_preinstall_check();
882 available_pkgs = pkg_vec_alloc();
884 pkg_hash_fetch_available(available_pkgs);
886 pkg_hash_fetch_all_installed(available_pkgs);
888 for (i=0; i<argc; i++) {
889 for (j=0; j<available_pkgs->len; j++) {
890 pkg = available_pkgs->pkgs[j];
892 if (fnmatch(argv[i], pkg->name, conf->nocase) != 0)
895 depends_count = pkg->depends_count +
896 pkg->pre_depends_count +
897 pkg->recommends_count +
900 opkg_msg(NOTICE, "%s depends on:\n", pkg->name);
902 for (k=0; k<depends_count; k++) {
903 cdep = &pkg->depends[k];
905 if (cdep->type != DEPEND)
908 str = pkg_depend_str(pkg, k);
909 opkg_msg(NOTICE, "\t%s\n", str);
916 pkg_vec_free(available_pkgs);
921 pkg_mark_provides(pkg_t *pkg)
923 int provides_count = pkg->provides_count;
924 abstract_pkg_t **provides = pkg->provides;
926 pkg->parent->state_flag |= SF_MARKED;
927 for (i = 0; i < provides_count; i++) {
928 provides[i]->state_flag |= SF_MARKED;
933 enum what_field_type {
943 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive, int argc, char **argv)
945 depend_t *possibility;
946 compound_depend_t *cdep;
947 pkg_vec_t *available_pkgs;
951 const char *rel_str = NULL;
954 switch (what_field_type) {
955 case DEPEND: rel_str = "depends on"; break;
956 case CONFLICTS: rel_str = "conflicts with"; break;
957 case SUGGEST: rel_str = "suggests"; break;
958 case RECOMMEND: rel_str = "recommends"; break;
962 available_pkgs = pkg_vec_alloc();
965 pkg_hash_fetch_available(available_pkgs);
967 pkg_hash_fetch_all_installed(available_pkgs);
969 /* mark the root set */
970 pkg_vec_clear_marks(available_pkgs);
971 opkg_msg(NOTICE, "Root set:\n");
972 for (i = 0; i < argc; i++)
973 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
975 for (i = 0; i < available_pkgs->len; i++) {
976 pkg = available_pkgs->pkgs[i];
977 if (pkg->state_flag & SF_MARKED) {
978 /* mark the parent (abstract) package */
979 pkg_mark_provides(pkg);
980 opkg_msg(NOTICE, " %s\n", pkg->name);
984 opkg_msg(NOTICE, "What %s root set\n", rel_str);
988 for (j=0; j<available_pkgs->len; j++) {
990 pkg = available_pkgs->pkgs[j];
991 count = ((what_field_type == CONFLICTS)
992 ? pkg->conflicts_count
993 : pkg->pre_depends_count +
995 pkg->recommends_count +
996 pkg->suggests_count);
998 /* skip this package if it is already marked */
999 if (pkg->parent->state_flag & SF_MARKED)
1002 for (k=0; k<count; k++) {
1003 cdep = (what_field_type == CONFLICTS)
1004 ? &pkg->conflicts[k]
1007 if (what_field_type != cdep->type)
1010 for (l=0; l<cdep->possibility_count; l++) {
1011 possibility = cdep->possibilities[l];
1013 if ((possibility->pkg->state_flag
1018 /* mark the depending package so we
1019 * won't visit it again */
1020 pkg->state_flag |= SF_MARKED;
1021 pkg_mark_provides(pkg);
1024 ver = pkg_version_str_alloc(pkg);
1025 opkg_msg(NOTICE, "\t%s %s\t%s %s",
1029 possibility->pkg->name);
1031 if (possibility->version) {
1032 opkg_msg(NOTICE, " (%s%s)",
1033 constraint_to_str(possibility->constraint),
1034 possibility->version);
1036 if (!pkg_dependence_satisfiable(possibility))
1039 opkg_message(NOTICE, "\n");
1046 } while (changed && recursive);
1048 pkg_vec_free(available_pkgs);
1054 opkg_whatdepends_recursively_cmd(int argc, char **argv)
1056 return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv);
1060 opkg_whatdepends_cmd(int argc, char **argv)
1062 return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv);
1066 opkg_whatsuggests_cmd(int argc, char **argv)
1068 return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv);
1072 opkg_whatrecommends_cmd(int argc, char **argv)
1074 return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv);
1078 opkg_whatconflicts_cmd(int argc, char **argv)
1080 return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv);
1084 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc, char **argv)
1088 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1089 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1092 pkg_info_preinstall_check();
1094 if (conf->query_all)
1095 pkg_hash_fetch_available(available_pkgs);
1097 pkg_hash_fetch_all_installed(available_pkgs);
1098 for (i = 0; i < argc; i++) {
1099 const char *target = argv[i];
1102 opkg_msg(NOTICE, "What %s %s\n",
1104 for (j = 0; j < available_pkgs->len; j++) {
1105 pkg_t *pkg = available_pkgs->pkgs[j];
1107 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1108 for (k = 0; k < count; k++) {
1109 abstract_pkg_t *apkg =
1110 ((what_field_type == WHATPROVIDES)
1112 : pkg->replaces[k]);
1113 if (fnmatch(target, apkg->name, conf->nocase) == 0) {
1114 opkg_msg(NOTICE, " %s", pkg->name);
1115 if ((conf->nocase ? strcasecmp(target, apkg->name) : strcmp(target, apkg->name)) != 0)
1116 opkg_msg(NOTICE, "\t%s %s\n",
1117 rel_str, apkg->name);
1118 opkg_message(NOTICE, "\n");
1123 pkg_vec_free(available_pkgs);
1129 opkg_whatprovides_cmd(int argc, char **argv)
1131 return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv);
1135 opkg_whatreplaces_cmd(int argc, char **argv)
1137 return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv);
1141 opkg_search_cmd(int argc, char **argv)
1145 pkg_vec_t *installed;
1147 str_list_t *installed_files;
1148 str_list_elt_t *iter;
1149 char *installed_file;
1155 installed = pkg_vec_alloc();
1156 pkg_hash_fetch_all_installed(installed);
1157 pkg_vec_sort(installed, pkg_compare_names);
1159 for (i=0; i < installed->len; i++) {
1160 pkg = installed->pkgs[i];
1162 installed_files = pkg_get_installed_files(pkg);
1164 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1165 installed_file = (char *)iter->data;
1166 if (fnmatch(argv[0], installed_file, conf->nocase)==0)
1170 pkg_free_installed_files(pkg);
1173 pkg_vec_free(installed);
1179 opkg_compare_versions_cmd(int argc, char **argv)
1182 /* this is a bit gross */
1184 parse_version(&p1, argv[0]);
1185 parse_version(&p2, argv[2]);
1186 return pkg_version_satisfied(&p1, &p2, argv[1]);
1189 "opkg compare_versions <v1> <op> <v2>\n"
1190 "<op> is one of <= >= << >> =\n");
1196 opkg_print_architecture_cmd(int argc, char **argv)
1198 nv_pair_list_elt_t *l;
1200 list_for_each_entry(l, &conf->arch_list.head, node) {
1201 nv_pair_t *nv = (nv_pair_t *)l->data;
1202 printf("arch %s %s\n", nv->name, nv->value);
1208 /* XXX: CLEANUP: The usage strings should be incorporated into this
1209 array for easier maintenance */
1210 static opkg_cmd_t cmds[] = {
1211 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1212 {"upgrade", 1, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1213 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd, PFM_SOURCE},
1214 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE},
1215 {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE},
1216 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE},
1217 {"list-upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE},
1218 {"list_changed_conffiles", 0, (opkg_cmd_fun_t)opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1219 {"list-changed-conffiles", 0, (opkg_cmd_fun_t)opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1220 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd, 0},
1221 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1222 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1223 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1224 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1225 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1226 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1227 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1228 {"find", 1, (opkg_cmd_fun_t)opkg_find_cmd, PFM_SOURCE},
1229 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1230 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1231 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1232 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1233 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1234 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1235 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1236 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1237 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1238 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1239 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1240 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1241 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1242 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1243 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1247 opkg_cmd_find(const char *name)
1251 int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
1253 for (i=0; i < num_cmds; i++) {
1255 if (strcmp(name, cmd->name) == 0)
1263 opkg_cmd_exec(opkg_cmd_t *cmd, int argc, const char **argv)
1265 return (cmd->fun)(argc, argv);