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.
24 #include "opkg_conf.h"
26 #include "opkg_message.h"
29 #include "pkg_parse.h"
30 #include "sprintf_alloc.h"
32 #include "file_util.h"
34 #include "libbb/libbb.h"
35 #include "opkg_utils.h"
36 #include "opkg_defines.h"
37 #include "opkg_download.h"
38 #include "opkg_install.h"
39 #include "opkg_upgrade.h"
40 #include "opkg_remove.h"
41 #include "opkg_configure.h"
42 #include "opkg_message.h"
46 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv);
47 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv);
48 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv);
49 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv);
50 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv);
51 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv);
52 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv);
53 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv);
54 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv);
55 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
56 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv);
57 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
58 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
70 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
71 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
72 static int pkg_mark_provides(pkg_t *pkg);
74 /* XXX: CLEANUP: The usage strings should be incorporated into this
75 array for easier maintenance */
76 static opkg_cmd_t cmds[] = {
77 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
78 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
79 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
80 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
81 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
82 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
83 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
84 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
85 {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd},
86 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
87 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
88 {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
89 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
90 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
91 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
92 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
93 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
94 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
95 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
96 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
97 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
98 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
99 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
100 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
101 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
102 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
103 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
104 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
105 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
106 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
109 static void print_pkg(pkg_t *pkg)
111 char *version = pkg_version_str_alloc(pkg);
112 if (pkg->description)
113 printf("%s - %s - %s\n", pkg->name, version, pkg->description);
115 printf("%s - %s\n", pkg->name, version);
119 int opkg_state_changed;
120 static void write_status_files_if_changed(opkg_conf_t *conf)
122 if (opkg_state_changed && !conf->noaction) {
123 opkg_message(conf, OPKG_INFO,
124 " writing status file\n");
125 opkg_conf_write_status_files(conf);
126 pkg_write_changed_filelists(conf);
128 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
133 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
135 opkg_cmd_t *opkg_cmd_find(const char *name)
140 for (i=0; i < num_cmds; i++) {
142 if (strcmp(name, cmd->name) == 0) {
150 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
154 result = (cmd->fun)(conf, argc, argv);
162 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
168 pkg_src_list_elt_t *iter;
172 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
174 if (! file_is_dir(lists_dir)) {
175 if (file_exists(lists_dir)) {
176 opkg_message(conf, OPKG_ERROR,
177 "%s: ERROR: %s exists, but is not a directory\n",
178 __FUNCTION__, lists_dir);
182 err = file_mkdir_hier(lists_dir, 0755);
184 opkg_message(conf, OPKG_ERROR,
185 "%s: ERROR: failed to make directory %s: %s\n",
186 __FUNCTION__, lists_dir, strerror(errno));
194 sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
195 if (mkdtemp (tmp) == NULL) {
201 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
202 char *url, *list_file_name;
204 src = (pkg_src_t *)iter->data;
206 if (src->extra_data) /* debian style? */
207 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
208 src->gzip ? "Packages.gz" : "Packages");
210 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
212 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
217 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
218 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
220 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
221 in = fopen (tmp_file_name, "r");
222 out = fopen (list_file_name, "w");
231 unlink (tmp_file_name);
235 err = opkg_download(conf, url, list_file_name, NULL, NULL);
239 opkg_message(conf, OPKG_NOTICE,
240 "Updated list of available packages in %s\n",
244 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
245 if (conf->check_signature) {
246 /* download detached signitures to verify the package lists */
247 /* get the url for the sig file */
248 if (src->extra_data) /* debian style? */
249 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
252 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
254 /* create temporary file for it */
257 /* Put the signature in the right place */
258 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
260 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
263 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
266 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
268 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
270 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
272 /* We shouldn't unlink the signature ! */
273 // unlink (tmp_file_name);
274 free (tmp_file_name);
280 free(list_file_name);
290 struct opkg_intercept
296 typedef struct opkg_intercept *opkg_intercept_t;
298 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
300 opkg_intercept_t ctx;
303 ctx = xcalloc(1, sizeof (*ctx));
304 ctx->oldpath = xstrdup(getenv("PATH"));
305 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
306 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX", conf->tmp_dir);
308 if (mkdtemp(ctx->statedir) == NULL) {
309 fprintf(stderr, "%s: mkdtemp: %s\n", __FUNCTION__, strerror(errno));
317 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
318 setenv("PATH", newpath, 1);
324 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
329 setenv ("PATH", ctx->oldpath, 1);
332 dir = opendir (ctx->statedir);
335 while (de = readdir (dir), de != NULL) {
338 if (de->d_name[0] == '.')
341 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
342 if (access (path, X_OK) == 0) {
343 const char *argv[] = {"sh", "-c", path, NULL};
350 perror (ctx->statedir);
353 free (ctx->statedir);
359 /* For package pkg do the following: If it is already visited, return. If not,
360 add it in visited list and recurse to its deps. Finally, add it to ordered
362 pkg_vec all contains all available packages in repos.
363 pkg_vec visited contains packages already visited by this function, and is
364 used to end recursion and avoid an infinite loop on graph cycles.
365 pkg_vec ordered will finally contain the ordered set of packages.
367 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
368 pkg_vec_t *visited, pkg_vec_t *ordered)
373 compound_depend_t * compound_depend;
374 depend_t ** possible_satisfiers;
375 abstract_pkg_t *abpkg;
376 abstract_pkg_t **dependents;
378 /* If it's just an available package, that is, not installed and not even
380 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
381 would do here. However, if there is an intermediate node (pkg) that is
382 configured and installed between two unpacked packages, the latter
383 won't be properly reordered, unless all installed/unpacked pkgs are
385 if (pkg->state_status == SS_NOT_INSTALLED)
388 /* If the package has already been visited (by this function), skip it */
389 for(j = 0; j < visited->len; j++)
390 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
391 opkg_message(conf, OPKG_INFO,
392 " pkg: %s already visited\n", pkg->name);
396 pkg_vec_insert(visited, pkg);
398 count = pkg->pre_depends_count + pkg->depends_count + \
399 pkg->recommends_count + pkg->suggests_count;
401 opkg_message(conf, OPKG_INFO,
402 " pkg: %s\n", pkg->name);
404 /* Iterate over all the dependencies of pkg. For each one, find a package
405 that is either installed or unpacked and satisfies this dependency.
406 (there should only be one such package per dependency installed or
407 unpacked). Then recurse to the dependency package */
408 for (j=0; j < count ; j++) {
409 compound_depend = &pkg->depends[j];
410 possible_satisfiers = compound_depend->possibilities;
411 for (k=0; k < compound_depend->possibility_count ; k++) {
412 abpkg = possible_satisfiers[k]->pkg;
413 dependents = abpkg->provided_by->pkgs;
415 if (dependents != NULL)
416 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
417 opkg_message(conf, OPKG_INFO,
418 " Descending on pkg: %s\n",
419 dependents [l]->name);
421 /* find whether dependent l is installed or unpacked,
422 * and then find which package in the list satisfies it */
423 for(m = 0; m < all->len; m++) {
425 if ( dep->state_status != SS_NOT_INSTALLED)
426 if ( ! strcmp(dep->name, dependents[l]->name)) {
427 opkg_recurse_pkgs_in_order(conf, dep, all,
429 /* Stop the outer loop */
430 l = abpkg->provided_by->len;
431 /* break from the inner loop */
440 /* When all recursions from this node down, are over, and all
441 dependencies have been added in proper order in the ordered array, add
442 also the package pkg to ordered array */
443 pkg_vec_insert(ordered, pkg);
449 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
451 pkg_vec_t *all, *ordered, *visited;
457 opkg_message(conf, OPKG_INFO,
458 "Configuring unpacked packages\n");
461 all = pkg_vec_alloc();
463 pkg_hash_fetch_available(&conf->pkg_hash, all);
465 /* Reorder pkgs in order to be configured according to the Depends: tag
467 opkg_message(conf, OPKG_INFO,
468 "Reordering packages before configuring them...\n");
469 ordered = pkg_vec_alloc();
470 visited = pkg_vec_alloc();
471 for(i = 0; i < all->len; i++) {
473 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
476 ic = opkg_prep_intercepts (conf);
482 for(i = 0; i < all->len; i++) {
485 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
488 if (pkg->state_status == SS_UNPACKED) {
489 opkg_message(conf, OPKG_NOTICE,
490 "Configuring %s\n", pkg->name);
492 r = opkg_configure(conf, pkg);
494 pkg->state_status = SS_INSTALLED;
495 pkg->parent->state_status = SS_INSTALLED;
496 pkg->state_flag &= ~SF_PREFER;
504 r = opkg_finalize_intercepts (ic);
510 pkg_vec_free(ordered);
511 pkg_vec_free(visited);
516 static opkg_conf_t *global_conf;
518 static void sigint_handler(int sig)
520 signal(sig, SIG_DFL);
521 opkg_message(NULL, OPKG_NOTICE,
522 "opkg: interrupted. writing out status database\n");
523 write_status_files_if_changed(global_conf);
527 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
534 signal(SIGINT, sigint_handler);
537 * Now scan through package names and install
539 for (i=0; i < argc; i++) {
542 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
543 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
544 if (err != EINVAL && err != 0)
547 pkg_info_preinstall_check(conf);
549 for (i=0; i < argc; i++) {
551 err = opkg_install_by_name(conf, arg);
552 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
553 opkg_message(conf, OPKG_ERROR,
554 "Cannot find package %s.\n",
559 opkg_configure_packages(conf, NULL);
561 write_status_files_if_changed(conf);
566 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
573 signal(SIGINT, sigint_handler);
576 for (i=0; i < argc; i++) {
579 err = opkg_prepare_url_for_install(conf, arg, &arg);
580 if (err != EINVAL && err != 0)
583 pkg_info_preinstall_check(conf);
585 for (i=0; i < argc; i++) {
587 if (conf->restrict_to_default_dest) {
588 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
592 opkg_message(conf, OPKG_NOTICE,
593 "Package %s not installed in %s\n",
594 argv[i], conf->default_dest->name);
598 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
602 opkg_upgrade_pkg(conf, pkg);
604 opkg_install_by_name(conf, arg);
608 pkg_vec_t *installed = pkg_vec_alloc();
610 pkg_info_preinstall_check(conf);
612 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
613 for (i = 0; i < installed->len; i++) {
614 pkg = installed->pkgs[i];
615 opkg_upgrade_pkg(conf, pkg);
617 pkg_vec_free(installed);
620 opkg_configure_packages(conf, NULL);
622 write_status_files_if_changed(conf);
627 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
633 pkg_info_preinstall_check(conf);
634 for (i = 0; i < argc; i++) {
637 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
639 opkg_message(conf, OPKG_ERROR,
640 "Cannot find package %s.\n"
641 "Check the spelling or perhaps run 'opkg update'\n",
646 err = opkg_download_pkg(conf, pkg, ".");
649 opkg_message(conf, OPKG_ERROR,
650 "Failed to download %s\n", pkg->name);
652 opkg_message(conf, OPKG_NOTICE,
653 "Downloaded %s as %s\n",
654 pkg->name, pkg->local_filename);
662 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
665 pkg_vec_t *available;
667 char *pkg_name = NULL;
672 available = pkg_vec_alloc();
673 pkg_hash_fetch_available(&conf->pkg_hash, available);
674 pkg_vec_sort(available, pkg_compare_names);
675 for (i=0; i < available->len; i++) {
676 pkg = available->pkgs[i];
677 /* if we have package name or pattern and pkg does not match, then skip it */
678 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
682 pkg_vec_free(available);
688 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
691 pkg_vec_t *available;
693 char *pkg_name = NULL;
698 available = pkg_vec_alloc();
699 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
700 pkg_vec_sort(available, pkg_compare_names);
701 for (i=0; i < available->len; i++) {
702 pkg = available->pkgs[i];
703 /* if we have package name or pattern and pkg does not match, then skip it */
704 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
709 pkg_vec_free(available);
714 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
716 struct active_list *head = prepare_upgrade_list(conf);
717 struct active_list *node=NULL;
718 pkg_t *_old_pkg, *_new_pkg;
720 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
721 _old_pkg = list_entry(node, pkg_t, list);
722 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
723 old_v = pkg_version_str_alloc(_old_pkg);
724 new_v = pkg_version_str_alloc(_new_pkg);
725 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
729 active_list_head_delete(head);
733 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
736 pkg_vec_t *available;
738 char *pkg_name = NULL;
744 available = pkg_vec_alloc();
746 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
748 pkg_hash_fetch_available(&conf->pkg_hash, available);
750 for (i=0; i < available->len; i++) {
751 pkg = available->pkgs[i];
752 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
756 pkg_formatted_info(stdout, pkg);
758 if (conf->verbosity >= OPKG_NOTICE) {
759 conffile_list_elt_t *iter;
760 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
761 conffile_t *cf = (conffile_t *)iter->data;
762 int modified = conffile_has_been_modified(conf, cf);
764 opkg_message(conf, OPKG_NOTICE,
765 "conffile=%s md5sum=%s modified=%d\n",
766 cf->name, cf->value, modified);
770 pkg_vec_free(available);
775 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
777 return opkg_info_status_cmd(conf, argc, argv, 0);
780 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
782 return opkg_info_status_cmd(conf, argc, argv, 1);
785 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
790 char *pkg_name = NULL;
794 err = opkg_configure_packages (conf, pkg_name);
797 err = opkg_configure_packages (conf, NULL);
800 write_status_files_if_changed(conf);
805 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
811 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
812 err = glob(globpattern, 0, NULL, &globbuf);
818 opkg_message(conf, OPKG_NOTICE,
819 "The following packages in %s will now be installed.\n",
821 for (i = 0; i < globbuf.gl_pathc; i++) {
822 opkg_message(conf, OPKG_NOTICE,
823 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
825 opkg_message(conf, OPKG_NOTICE, "\n");
826 for (i = 0; i < globbuf.gl_pathc; i++) {
827 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
829 err = unlink(globbuf.gl_pathv[i]);
831 opkg_message(conf, OPKG_ERROR,
832 "%s: ERROR: failed to unlink %s: %s\n",
833 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
843 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
847 pkg_t *pkg_to_remove;
848 pkg_vec_t *available;
849 char *pkg_name = NULL;
851 signal(SIGINT, sigint_handler);
853 // ENH: Add the "no pkg removed" just in case.
857 pkg_info_preinstall_check(conf);
859 available = pkg_vec_alloc();
860 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
861 for (i=0; i < argc; i++) {
862 pkg_name = xcalloc(1, strlen(argv[i])+2);
863 strcpy(pkg_name,argv[i]);
864 for (a=0; a < available->len; a++) {
865 pkg = available->pkgs[a];
866 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
869 if (conf->restrict_to_default_dest) {
870 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
874 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
877 if (pkg_to_remove == NULL) {
878 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
881 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
882 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
885 opkg_remove_pkg(conf, pkg_to_remove,0);
890 pkg_vec_free(available);
892 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
894 int flagged_pkg_count = 0;
897 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
899 for (i = 0; i < installed_pkgs->len; i++) {
900 pkg_t *pkg = installed_pkgs->pkgs[i];
901 if (pkg->state_flag & SF_USER) {
904 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
905 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
908 if (!flagged_pkg_count) {
909 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
910 "so refusing to uninstall unflagged non-leaf packages\n");
914 /* find packages not flagged SF_USER (i.e., installed to
915 * satisfy a dependence) and not having any dependents, and
919 for (i = 0; i < installed_pkgs->len; i++) {
920 pkg_t *pkg = installed_pkgs->pkgs[i];
921 if (!(pkg->state_flag & SF_USER)
922 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
924 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
925 opkg_remove_pkg(conf, pkg,0);
930 pkg_vec_free(installed_pkgs);
934 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
936 write_status_files_if_changed(conf);
940 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
946 signal(SIGINT, sigint_handler);
948 pkg_info_preinstall_check(conf);
950 for (i=0; i < argc; i++) {
951 if (conf->restrict_to_default_dest) {
952 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
956 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
960 opkg_message(conf, OPKG_ERROR,
961 "Package %s is not installed.\n", argv[i]);
964 opkg_purge_pkg(conf, pkg);
967 write_status_files_if_changed(conf);
971 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
975 const char *flags = argv[0];
978 signal(SIGINT, sigint_handler);
980 for (i=1; i < argc; i++) {
981 if (conf->restrict_to_default_dest) {
982 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
986 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
990 opkg_message(conf, OPKG_ERROR,
991 "Package %s is not installed.\n", argv[i]);
994 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
995 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
996 pkg->state_flag = pkg_state_flag_from_str(flags);
998 /* pb_ asked this feature 03292004 */
999 /* Actually I will use only this two, but this is an open for various status */
1000 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1001 pkg->state_status = pkg_state_status_from_str(flags);
1003 opkg_state_changed++;
1004 opkg_message(conf, OPKG_NOTICE,
1005 "Setting flags for package %s to %s\n",
1009 write_status_files_if_changed(conf);
1013 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1017 str_list_elt_t *iter;
1024 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1027 opkg_message(conf, OPKG_ERROR,
1028 "Package %s not installed.\n", argv[0]);
1032 files = pkg_get_installed_files(conf, pkg);
1033 pkg_version = pkg_version_str_alloc(pkg);
1035 printf("Package %s (%s) is installed on %s and has the following files:\n",
1036 pkg->name, pkg_version, pkg->dest->name);
1038 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
1039 printf("%s\n", (char *)iter->data);
1042 pkg_free_installed_files(pkg);
1047 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1051 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1052 const char *rel_str = "depends on";
1055 pkg_info_preinstall_check(conf);
1057 if (conf->query_all)
1058 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1060 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1061 for (i = 0; i < argc; i++) {
1062 const char *target = argv[i];
1065 opkg_message(conf, OPKG_NOTICE, "target=%s\n", target);
1067 for (j = 0; j < available_pkgs->len; j++) {
1068 pkg_t *pkg = available_pkgs->pkgs[j];
1069 if (fnmatch(target, pkg->name, 0) == 0) {
1071 int count = pkg->depends_count + pkg->pre_depends_count;
1072 opkg_message(conf, OPKG_NOTICE, "What %s (arch=%s) %s\n",
1073 target, pkg->architecture, rel_str);
1074 for (k = 0; k < count; k++) {
1075 compound_depend_t *cdepend = &pkg->depends[k];
1077 for (l = 0; l < cdepend->possibility_count; l++) {
1078 depend_t *possibility = cdepend->possibilities[l];
1079 opkg_message(conf, OPKG_NOTICE, " %s", possibility->pkg->name);
1080 if (conf->verbosity >= OPKG_NOTICE) {
1081 if (possibility->version) {
1082 char *typestr = NULL;
1083 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1084 switch (possibility->constraint) {
1085 case NONE: typestr = "none"; break;
1086 case EARLIER: typestr = "<"; break;
1087 case EARLIER_EQUAL: typestr = "<="; break;
1088 case EQUAL: typestr = "="; break;
1089 case LATER_EQUAL: typestr = ">="; break;
1090 case LATER: typestr = ">"; break;
1092 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1095 opkg_message(conf, OPKG_NOTICE, "\n");
1101 pkg_vec_free(available_pkgs);
1106 enum what_field_type {
1115 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum depend_type what_field_type, int recursive, int argc, char **argv)
1119 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1120 const char *rel_str = NULL;
1124 switch (what_field_type) {
1125 case DEPEND: rel_str = "depends on"; break;
1126 case CONFLICTS: rel_str = "conflicts with"; break;
1127 case SUGGEST: rel_str = "suggests"; break;
1128 case RECOMMEND: rel_str = "recommends"; break;
1132 if (conf->query_all)
1133 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1135 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1137 /* mark the root set */
1138 pkg_vec_clear_marks(available_pkgs);
1139 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1140 for (i = 0; i < argc; i++) {
1141 const char *dependee_pattern = argv[i];
1142 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1144 for (i = 0; i < available_pkgs->len; i++) {
1145 pkg_t *pkg = available_pkgs->pkgs[i];
1146 if (pkg->state_flag & SF_MARKED) {
1147 /* mark the parent (abstract) package */
1148 pkg_mark_provides(pkg);
1149 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1153 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1158 for (j = 0; j < available_pkgs->len; j++) {
1159 pkg_t *pkg = available_pkgs->pkgs[j];
1161 int count = ((what_field_type == CONFLICTS)
1162 ? pkg->conflicts_count
1163 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1164 /* skip this package if it is already marked */
1165 if (pkg->parent->state_flag & SF_MARKED) {
1168 for (k = 0; k < count; k++) {
1169 compound_depend_t *cdepend =
1170 (what_field_type == CONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1172 if (what_field_type != cdepend->type)
1174 for (l = 0; l < cdepend->possibility_count; l++) {
1175 depend_t *possibility = cdepend->possibilities[l];
1176 if (possibility->pkg->state_flag & SF_MARKED) {
1177 /* mark the depending package so we won't visit it again */
1178 pkg->state_flag |= SF_MARKED;
1179 pkg_mark_provides(pkg);
1182 if (conf->verbosity >= OPKG_NOTICE) {
1183 char *ver = pkg_version_str_alloc(pkg);
1184 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1185 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1186 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1187 if (possibility->version) {
1188 char *typestr = NULL;
1189 switch (possibility->constraint) {
1190 case NONE: typestr = "none"; break;
1191 case EARLIER: typestr = "<"; break;
1192 case EARLIER_EQUAL: typestr = "<="; break;
1193 case EQUAL: typestr = "="; break;
1194 case LATER_EQUAL: typestr = ">="; break;
1195 case LATER: typestr = ">"; break;
1197 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1200 if (!pkg_dependence_satisfiable(conf, possibility))
1201 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1203 opkg_message(conf, OPKG_NOTICE, "\n");
1211 } while (changed && recursive);
1212 pkg_vec_free(available_pkgs);
1218 static int pkg_mark_provides(pkg_t *pkg)
1220 int provides_count = pkg->provides_count;
1221 abstract_pkg_t **provides = pkg->provides;
1223 pkg->parent->state_flag |= SF_MARKED;
1224 for (i = 0; i < provides_count; i++) {
1225 provides[i]->state_flag |= SF_MARKED;
1230 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1232 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 1, argc, argv);
1234 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1236 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 0, argc, argv);
1239 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1241 return opkg_what_depends_conflicts_cmd(conf, SUGGEST, 0, argc, argv);
1244 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1246 return opkg_what_depends_conflicts_cmd(conf, RECOMMEND, 0, argc, argv);
1249 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1251 return opkg_what_depends_conflicts_cmd(conf, CONFLICTS, 0, argc, argv);
1254 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1258 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1259 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1262 pkg_info_preinstall_check(conf);
1264 if (conf->query_all)
1265 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1267 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1268 for (i = 0; i < argc; i++) {
1269 const char *target = argv[i];
1272 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1274 for (j = 0; j < available_pkgs->len; j++) {
1275 pkg_t *pkg = available_pkgs->pkgs[j];
1277 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1278 for (k = 0; k < count; k++) {
1279 abstract_pkg_t *apkg =
1280 ((what_field_type == WHATPROVIDES)
1282 : pkg->replaces[k]);
1283 if (fnmatch(target, apkg->name, 0) == 0) {
1284 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1285 if (strcmp(target, apkg->name) != 0)
1286 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1287 opkg_message(conf, OPKG_ERROR, "\n");
1292 pkg_vec_free(available_pkgs);
1297 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1299 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1302 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1304 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1307 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1311 pkg_vec_t *installed;
1313 str_list_t *installed_files;
1314 str_list_elt_t *iter;
1315 char *installed_file;
1321 installed = pkg_vec_alloc();
1322 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1323 pkg_vec_sort(installed, pkg_compare_names);
1325 for (i=0; i < installed->len; i++) {
1326 pkg = installed->pkgs[i];
1328 installed_files = pkg_get_installed_files(conf, pkg);
1330 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1331 installed_file = (char *)iter->data;
1332 if (fnmatch(argv[0], installed_file, 0)==0)
1336 pkg_free_installed_files(pkg);
1339 pkg_vec_free(installed);
1344 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1347 /* this is a bit gross */
1349 parse_version(&p1, argv[0]);
1350 parse_version(&p2, argv[2]);
1351 return pkg_version_satisfied(&p1, &p2, argv[1]);
1353 opkg_message(conf, OPKG_ERROR,
1354 "opkg compare_versions <v1> <op> <v2>\n"
1355 "<op> is one of <= >= << >> =\n");
1360 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1362 nv_pair_list_elt_t *l;
1364 list_for_each_entry(l, &conf->arch_list.head, node) {
1365 nv_pair_t *nv = (nv_pair_t *)l->data;
1366 printf("arch %s %s\n", nv->name, nv->value);