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.
23 #include "opkg_conf.h"
25 #include "opkg_message.h"
28 #include "pkg_parse.h"
29 #include "sprintf_alloc.h"
31 #include "file_util.h"
33 #include "libbb/libbb.h"
34 #include "opkg_utils.h"
35 #include "opkg_defines.h"
40 #include "opkg_download.h"
41 #include "opkg_install.h"
42 #include "opkg_upgrade.h"
43 #include "opkg_remove.h"
44 #include "opkg_configure.h"
45 #include "opkg_message.h"
48 static void *p_userdata = NULL;
50 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv);
51 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv);
52 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv);
53 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv);
54 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv);
55 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv);
56 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv);
57 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv);
58 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
70 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
71 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
72 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
73 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
74 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
75 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
76 static int pkg_mark_provides(pkg_t *pkg);
78 /* XXX: CLEANUP: The usage strings should be incorporated into this
79 array for easier maintenance */
80 static opkg_cmd_t cmds[] = {
81 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
82 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
83 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
84 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
85 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
86 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
87 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
88 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
89 {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd},
90 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
91 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
92 {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
93 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
94 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
95 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
96 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
97 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
98 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
99 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
100 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
101 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
102 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
103 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
104 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
105 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
106 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
107 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
108 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
109 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
110 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
113 int opkg_state_changed;
114 static void write_status_files_if_changed(opkg_conf_t *conf)
116 if (opkg_state_changed && !conf->noaction) {
117 opkg_message(conf, OPKG_INFO,
118 " writing status file\n");
119 opkg_conf_write_status_files(conf);
120 pkg_write_changed_filelists(conf);
122 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
127 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
129 opkg_cmd_t *opkg_cmd_find(const char *name)
134 for (i=0; i < num_cmds; i++) {
136 if (strcmp(name, cmd->name) == 0) {
144 void opkg_print_error_list (opkg_conf_t *conf)
146 struct errlist *err = error_list;
149 reverse_error_list(&err);
151 printf ("Collected errors:\n");
152 /* Here we print the errors collected and free the list */
153 while (err != NULL) {
154 printf (" * %s", err->errmsg);
159 free_error_list(&error_list);
164 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
167 p_userdata = userdata;
170 result = (cmd->fun)(conf, argc, argv);
172 if ( result != 0 && !error_list) {
173 opkg_message(conf, OPKG_NOTICE, "An error occurred, return value: %d.\n", result);
176 opkg_print_error_list (conf);
182 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
188 pkg_src_list_elt_t *iter;
192 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
194 if (! file_is_dir(lists_dir)) {
195 if (file_exists(lists_dir)) {
196 opkg_message(conf, OPKG_ERROR,
197 "%s: ERROR: %s exists, but is not a directory\n",
198 __FUNCTION__, lists_dir);
202 err = file_mkdir_hier(lists_dir, 0755);
204 opkg_message(conf, OPKG_ERROR,
205 "%s: ERROR: failed to make directory %s: %s\n",
206 __FUNCTION__, lists_dir, strerror(errno));
215 tmp = strdup ("/tmp/opkg.XXXXXX");
217 if (mkdtemp (tmp) == NULL) {
223 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
224 char *url, *list_file_name;
226 src = (pkg_src_t *)iter->data;
228 if (src->extra_data) /* debian style? */
229 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
230 src->gzip ? "Packages.gz" : "Packages");
232 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
234 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
239 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
240 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
242 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
243 in = fopen (tmp_file_name, "r");
244 out = fopen (list_file_name, "w");
253 unlink (tmp_file_name);
257 err = opkg_download(conf, url, list_file_name, NULL, NULL);
261 opkg_message(conf, OPKG_NOTICE,
262 "Updated list of available packages in %s\n",
266 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
267 if (conf->check_signature) {
268 /* download detached signitures to verify the package lists */
269 /* get the url for the sig file */
270 if (src->extra_data) /* debian style? */
271 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
274 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
276 /* create temporary file for it */
279 /* Put the signature in the right place */
280 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
282 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
285 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
288 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
290 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
292 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
294 /* We shouldn't unlink the signature ! */
295 // unlink (tmp_file_name);
296 free (tmp_file_name);
302 free(list_file_name);
312 struct opkg_intercept
318 typedef struct opkg_intercept *opkg_intercept_t;
320 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
322 opkg_intercept_t ctx;
327 ctx = calloc (1, sizeof (*ctx));
328 oldpath = getenv ("PATH");
330 ctx->oldpath = strdup (oldpath);
336 sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
337 setenv ("PATH", newpath, 1);
342 sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
343 if (mkdir (ctx->statedir, 0770) < 0) {
344 if (errno == EEXIST) {
345 free (ctx->statedir);
349 perror (ctx->statedir);
352 setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
356 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
363 setenv ("PATH", ctx->oldpath, 1);
369 dir = opendir (ctx->statedir);
372 while (de = readdir (dir), de != NULL) {
375 if (de->d_name[0] == '.')
378 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
379 if (access (path, X_OK) == 0) {
389 perror (ctx->statedir);
391 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
395 free (ctx->statedir);
401 /* For package pkg do the following: If it is already visited, return. If not,
402 add it in visited list and recurse to its deps. Finally, add it to ordered
404 pkg_vec all contains all available packages in repos.
405 pkg_vec visited contains packages already visited by this function, and is
406 used to end recursion and avoid an infinite loop on graph cycles.
407 pkg_vec ordered will finally contain the ordered set of packages.
409 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
410 pkg_vec_t *visited, pkg_vec_t *ordered)
415 compound_depend_t * compound_depend;
416 depend_t ** possible_satisfiers;
417 abstract_pkg_t *abpkg;
418 abstract_pkg_t **dependents;
420 /* If it's just an available package, that is, not installed and not even
422 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
423 would do here. However, if there is an intermediate node (pkg) that is
424 configured and installed between two unpacked packages, the latter
425 won't be properly reordered, unless all installed/unpacked pkgs are
427 if (pkg->state_status == SS_NOT_INSTALLED)
430 /* If the package has already been visited (by this function), skip it */
431 for(j = 0; j < visited->len; j++)
432 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
433 opkg_message(conf, OPKG_INFO,
434 " pkg: %s already visited\n", pkg->name);
438 pkg_vec_insert(visited, pkg);
440 count = pkg->pre_depends_count + pkg->depends_count + \
441 pkg->recommends_count + pkg->suggests_count;
443 opkg_message(conf, OPKG_INFO,
444 " pkg: %s\n", pkg->name);
446 /* Iterate over all the dependencies of pkg. For each one, find a package
447 that is either installed or unpacked and satisfies this dependency.
448 (there should only be one such package per dependency installed or
449 unpacked). Then recurse to the dependency package */
450 for (j=0; j < count ; j++) {
451 compound_depend = &pkg->depends[j];
452 possible_satisfiers = compound_depend->possibilities;
453 for (k=0; k < compound_depend->possibility_count ; k++) {
454 abpkg = possible_satisfiers[k]->pkg;
455 dependents = abpkg->provided_by->pkgs;
457 if (dependents != NULL)
458 while (dependents [l] != NULL && l < abpkg->provided_by->len) {
459 opkg_message(conf, OPKG_INFO,
460 " Descending on pkg: %s\n",
461 dependents [l]->name);
463 /* find whether dependent l is installed or unpacked,
464 * and then find which package in the list satisfies it */
465 for(m = 0; m < all->len; m++) {
467 if ( dep->state_status != SS_NOT_INSTALLED)
468 if ( ! strcmp(dep->name, dependents[l]->name)) {
469 opkg_recurse_pkgs_in_order(conf, dep, all,
471 /* Stop the outer loop */
472 l = abpkg->provided_by->len;
473 /* break from the inner loop */
482 /* When all recursions from this node down, are over, and all
483 dependencies have been added in proper order in the ordered array, add
484 also the package pkg to ordered array */
485 pkg_vec_insert(ordered, pkg);
491 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
493 pkg_vec_t *all, *ordered, *visited;
499 opkg_message(conf, OPKG_INFO,
500 "Configuring unpacked packages\n");
503 all = pkg_vec_alloc();
505 pkg_hash_fetch_available(&conf->pkg_hash, all);
507 /* Reorder pkgs in order to be configured according to the Depends: tag
509 opkg_message(conf, OPKG_INFO,
510 "Reordering packages before configuring them...\n");
511 ordered = pkg_vec_alloc();
512 visited = pkg_vec_alloc();
513 for(i = 0; i < all->len; i++) {
515 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
519 ic = opkg_prep_intercepts (conf);
521 for(i = 0; i < all->len; i++) {
524 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
527 if (pkg->state_status == SS_UNPACKED) {
528 opkg_message(conf, OPKG_NOTICE,
529 "Configuring %s\n", pkg->name);
531 r = opkg_configure(conf, pkg);
533 pkg->state_status = SS_INSTALLED;
534 pkg->parent->state_status = SS_INSTALLED;
535 pkg->state_flag &= ~SF_PREFER;
543 r = opkg_finalize_intercepts (ic);
548 pkg_vec_free(ordered);
549 pkg_vec_free(visited);
554 static opkg_conf_t *global_conf;
556 static void sigint_handler(int sig)
558 signal(sig, SIG_DFL);
559 opkg_message(NULL, OPKG_NOTICE,
560 "opkg: interrupted. writing out status database\n");
561 write_status_files_if_changed(global_conf);
565 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
572 signal(SIGINT, sigint_handler);
575 * Now scan through package names and install
577 for (i=0; i < argc; i++) {
580 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
581 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
582 if (err != EINVAL && err != 0)
585 pkg_info_preinstall_check(conf);
587 for (i=0; i < argc; i++) {
589 err = opkg_install_by_name(conf, arg);
590 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
591 opkg_message(conf, OPKG_ERROR,
592 "Cannot find package %s.\n",
597 /* recheck to verify that all dependences are satisfied */
598 if (0) opkg_satisfy_all_dependences(conf);
600 opkg_configure_packages(conf, NULL);
602 write_status_files_if_changed(conf);
607 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
614 signal(SIGINT, sigint_handler);
617 for (i=0; i < argc; i++) {
620 err = opkg_prepare_url_for_install(conf, arg, &arg);
621 if (err != EINVAL && err != 0)
624 pkg_info_preinstall_check(conf);
626 for (i=0; i < argc; i++) {
628 if (conf->restrict_to_default_dest) {
629 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
633 opkg_message(conf, OPKG_NOTICE,
634 "Package %s not installed in %s\n",
635 argv[i], conf->default_dest->name);
639 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
643 opkg_upgrade_pkg(conf, pkg);
645 opkg_install_by_name(conf, arg);
649 pkg_vec_t *installed = pkg_vec_alloc();
651 pkg_info_preinstall_check(conf);
653 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
654 for (i = 0; i < installed->len; i++) {
655 pkg = installed->pkgs[i];
656 opkg_upgrade_pkg(conf, pkg);
658 pkg_vec_free(installed);
661 /* recheck to verify that all dependences are satisfied */
662 if (0) opkg_satisfy_all_dependences(conf);
664 opkg_configure_packages(conf, NULL);
666 write_status_files_if_changed(conf);
671 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
677 pkg_info_preinstall_check(conf);
678 for (i = 0; i < argc; i++) {
681 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
683 opkg_message(conf, OPKG_ERROR,
684 "Cannot find package %s.\n"
685 "Check the spelling or perhaps run 'opkg update'\n",
690 err = opkg_download_pkg(conf, pkg, ".");
693 opkg_message(conf, OPKG_ERROR,
694 "Failed to download %s\n", pkg->name);
696 opkg_message(conf, OPKG_NOTICE,
697 "Downloaded %s as %s\n",
698 pkg->name, pkg->local_filename);
706 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
709 pkg_vec_t *available;
711 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
713 char *pkg_name = NULL;
719 available = pkg_vec_alloc();
720 pkg_hash_fetch_available(&conf->pkg_hash, available);
721 pkg_vec_sort(available, pkg_compare_names);
722 for (i=0; i < available->len; i++) {
723 pkg = available->pkgs[i];
724 /* if we have package name or pattern and pkg does not match, then skip it */
725 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
727 if (pkg->description) {
728 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
730 desc_short[0] = '\0';
732 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
733 newline = strchr(desc_short, '\n');
738 version_str = pkg_version_str_alloc(pkg);
739 opkg_cb_list(pkg->name,desc_short,
746 pkg_vec_free(available);
752 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
755 pkg_vec_t *available;
757 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
759 char *pkg_name = NULL;
765 available = pkg_vec_alloc();
766 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
767 pkg_vec_sort(available, pkg_compare_names);
768 for (i=0; i < available->len; i++) {
769 pkg = available->pkgs[i];
770 /* if we have package name or pattern and pkg does not match, then skip it */
771 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
773 if (pkg->description) {
774 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
776 desc_short[0] = '\0';
778 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
779 newline = strchr(desc_short, '\n');
784 version_str = pkg_version_str_alloc(pkg);
785 opkg_cb_list(pkg->name,desc_short,
793 pkg_vec_free(available);
798 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
800 struct active_list *head = prepare_upgrade_list(conf);
801 struct active_list *node=NULL;
802 pkg_t *_old_pkg, *_new_pkg;
804 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
805 _old_pkg = list_entry(node, pkg_t, list);
806 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
807 old_v = pkg_version_str_alloc(_old_pkg);
808 new_v = pkg_version_str_alloc(_new_pkg);
810 opkg_cb_list(_old_pkg->name, new_v, old_v, _old_pkg->state_status, p_userdata);
814 active_list_head_delete(head);
818 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
821 pkg_vec_t *available;
823 char *pkg_name = NULL;
824 char **pkg_fields = NULL;
832 pkg_fields = &argv[1];
836 available = pkg_vec_alloc();
838 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
840 pkg_hash_fetch_available(&conf->pkg_hash, available);
841 for (i=0; i < available->len; i++) {
842 pkg = available->pkgs[i];
843 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
847 buff = pkg_formatted_info(pkg);
849 if (opkg_cb_status) opkg_cb_status(pkg->name,
854 We should not forget that actually the pointer is allocated.
855 We need to free it :) ( Thanks florian for seeing the error )
860 if (conf->verbosity > 1) {
861 conffile_list_elt_t *iter;
862 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
863 conffile_t *cf = (conffile_t *)iter->data;
864 int modified = conffile_has_been_modified(conf, cf);
865 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
866 cf->name, cf->value, modified);
870 pkg_vec_free(available);
875 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
877 return opkg_info_status_cmd(conf, argc, argv, 0);
880 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
882 return opkg_info_status_cmd(conf, argc, argv, 1);
885 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
890 char *pkg_name = NULL;
894 err = opkg_configure_packages (conf, pkg_name);
897 err = opkg_configure_packages (conf, NULL);
900 write_status_files_if_changed(conf);
905 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
911 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
912 err = glob(globpattern, 0, NULL, &globbuf);
918 opkg_message(conf, OPKG_NOTICE,
919 "The following packages in %s will now be installed.\n",
921 for (i = 0; i < globbuf.gl_pathc; i++) {
922 opkg_message(conf, OPKG_NOTICE,
923 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
925 opkg_message(conf, OPKG_NOTICE, "\n");
926 for (i = 0; i < globbuf.gl_pathc; i++) {
927 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
929 err = unlink(globbuf.gl_pathv[i]);
931 opkg_message(conf, OPKG_ERROR,
932 "%s: ERROR: failed to unlink %s: %s\n",
933 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
943 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
947 pkg_t *pkg_to_remove;
948 pkg_vec_t *available;
949 char *pkg_name = NULL;
951 signal(SIGINT, sigint_handler);
953 // ENH: Add the "no pkg removed" just in case.
957 pkg_info_preinstall_check(conf);
959 available = pkg_vec_alloc();
960 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
961 for (i=0; i < argc; i++) {
962 pkg_name = calloc(1, strlen(argv[i])+2);
963 strcpy(pkg_name,argv[i]);
964 for (a=0; a < available->len; a++) {
965 pkg = available->pkgs[a];
966 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
969 if (conf->restrict_to_default_dest) {
970 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
974 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
978 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
981 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
982 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
985 opkg_remove_pkg(conf, pkg_to_remove,0);
990 pkg_vec_free(available);
992 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
994 int flagged_pkg_count = 0;
997 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
999 for (i = 0; i < installed_pkgs->len; i++) {
1000 pkg_t *pkg = installed_pkgs->pkgs[i];
1001 if (pkg->state_flag & SF_USER) {
1002 flagged_pkg_count++;
1004 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
1005 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
1008 if (!flagged_pkg_count) {
1009 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
1010 "so refusing to uninstall unflagged non-leaf packages\n");
1014 /* find packages not flagged SF_USER (i.e., installed to
1015 * satisfy a dependence) and not having any dependents, and
1019 for (i = 0; i < installed_pkgs->len; i++) {
1020 pkg_t *pkg = installed_pkgs->pkgs[i];
1021 if (!(pkg->state_flag & SF_USER)
1022 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1024 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1025 opkg_remove_pkg(conf, pkg,0);
1030 pkg_vec_free(installed_pkgs);
1034 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1036 write_status_files_if_changed(conf);
1040 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1046 signal(SIGINT, sigint_handler);
1048 pkg_info_preinstall_check(conf);
1050 for (i=0; i < argc; i++) {
1051 if (conf->restrict_to_default_dest) {
1052 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1054 conf->default_dest);
1056 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1060 opkg_message(conf, OPKG_ERROR,
1061 "Package %s is not installed.\n", argv[i]);
1064 opkg_purge_pkg(conf, pkg);
1067 write_status_files_if_changed(conf);
1071 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1075 const char *flags = argv[0];
1078 signal(SIGINT, sigint_handler);
1080 for (i=1; i < argc; i++) {
1081 if (conf->restrict_to_default_dest) {
1082 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1084 conf->default_dest);
1086 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1090 opkg_message(conf, OPKG_ERROR,
1091 "Package %s is not installed.\n", argv[i]);
1094 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1095 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1096 pkg->state_flag = pkg_state_flag_from_str(flags);
1098 /* pb_ asked this feature 03292004 */
1099 /* Actually I will use only this two, but this is an open for various status */
1100 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1101 pkg->state_status = pkg_state_status_from_str(flags);
1103 opkg_state_changed++;
1104 opkg_message(conf, OPKG_NOTICE,
1105 "Setting flags for package %s to %s\n",
1109 write_status_files_if_changed(conf);
1113 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1116 str_list_t *installed_files;
1117 str_list_elt_t *iter;
1119 size_t buff_len = 8192;
1123 buff = (char *)calloc(1, buff_len);
1124 if ( buff == NULL ) {
1125 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1133 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1136 opkg_message(conf, OPKG_ERROR,
1137 "Package %s not installed.\n", argv[0]);
1141 installed_files = pkg_get_installed_files(pkg);
1142 pkg_version = pkg_version_str_alloc(pkg);
1146 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1147 pkg->name, pkg_version, pkg->dest->name) + 1;
1148 if (used_len > buff_len) {
1150 buff = realloc (buff, buff_len);
1153 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1154 used_len += strlen (iter->data) + 1;
1155 while (buff_len <= used_len) {
1157 buff = realloc (buff, buff_len);
1159 strncat(buff, iter->data, buff_len);
1160 strncat(buff, "\n", buff_len);
1162 if (opkg_cb_list) opkg_cb_list(pkg->name,
1164 pkg_version_str_alloc(pkg),
1171 pkg_free_installed_files(pkg);
1176 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1180 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1181 const char *rel_str = "depends on";
1184 pkg_info_preinstall_check(conf);
1186 if (conf->query_all)
1187 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1189 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1190 for (i = 0; i < argc; i++) {
1191 const char *target = argv[i];
1194 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1196 for (j = 0; j < available_pkgs->len; j++) {
1197 pkg_t *pkg = available_pkgs->pkgs[j];
1198 if (fnmatch(target, pkg->name, 0) == 0) {
1200 int count = pkg->depends_count + pkg->pre_depends_count;
1201 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1202 target, pkg->architecture, rel_str);
1203 for (k = 0; k < count; k++) {
1204 compound_depend_t *cdepend = &pkg->depends[k];
1206 for (l = 0; l < cdepend->possibility_count; l++) {
1207 depend_t *possibility = cdepend->possibilities[l];
1208 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1209 if (conf->verbosity > 0) {
1210 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1211 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1212 if (possibility->version) {
1213 char *typestr = NULL;
1214 switch (possibility->constraint) {
1215 case NONE: typestr = "none"; break;
1216 case EARLIER: typestr = "<"; break;
1217 case EARLIER_EQUAL: typestr = "<="; break;
1218 case EQUAL: typestr = "="; break;
1219 case LATER_EQUAL: typestr = ">="; break;
1220 case LATER: typestr = ">"; break;
1222 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1226 opkg_message(conf, OPKG_ERROR, "\n");
1232 pkg_vec_free(available_pkgs);
1237 enum what_field_type {
1246 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1250 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1251 const char *rel_str = NULL;
1255 switch (what_field_type) {
1256 case WHATDEPENDS: rel_str = "depends on"; break;
1257 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1258 case WHATSUGGESTS: rel_str = "suggests"; break;
1259 case WHATRECOMMENDS: rel_str = "recommends"; break;
1260 case WHATPROVIDES: rel_str = "provides"; break;
1261 case WHATREPLACES: rel_str = "replaces"; break;
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);
1269 /* mark the root set */
1270 pkg_vec_clear_marks(available_pkgs);
1271 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1272 for (i = 0; i < argc; i++) {
1273 const char *dependee_pattern = argv[i];
1274 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1276 for (i = 0; i < available_pkgs->len; i++) {
1277 pkg_t *pkg = available_pkgs->pkgs[i];
1278 if (pkg->state_flag & SF_MARKED) {
1279 /* mark the parent (abstract) package */
1280 pkg_mark_provides(pkg);
1281 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1285 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1290 for (j = 0; j < available_pkgs->len; j++) {
1291 pkg_t *pkg = available_pkgs->pkgs[j];
1293 int count = ((what_field_type == WHATCONFLICTS)
1294 ? pkg->conflicts_count
1295 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1296 /* skip this package if it is already marked */
1297 if (pkg->parent->state_flag & SF_MARKED) {
1300 for (k = 0; k < count; k++) {
1301 compound_depend_t *cdepend =
1302 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1304 for (l = 0; l < cdepend->possibility_count; l++) {
1305 depend_t *possibility = cdepend->possibilities[l];
1306 if (possibility->pkg->state_flag & SF_MARKED) {
1307 /* mark the depending package so we won't visit it again */
1308 pkg->state_flag |= SF_MARKED;
1309 pkg_mark_provides(pkg);
1312 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1313 if (conf->verbosity > 0) {
1314 char *ver = pkg_version_str_alloc(pkg);
1315 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1316 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1317 if (possibility->version) {
1318 char *typestr = NULL;
1319 switch (possibility->constraint) {
1320 case NONE: typestr = "none"; break;
1321 case EARLIER: typestr = "<"; break;
1322 case EARLIER_EQUAL: typestr = "<="; break;
1323 case EQUAL: typestr = "="; break;
1324 case LATER_EQUAL: typestr = ">="; break;
1325 case LATER: typestr = ">"; break;
1327 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1330 if (!pkg_dependence_satisfiable(conf, possibility))
1331 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1333 opkg_message(conf, OPKG_NOTICE, "\n");
1341 } while (changed && recursive);
1342 pkg_vec_free(available_pkgs);
1348 static int pkg_mark_provides(pkg_t *pkg)
1350 int provides_count = pkg->provides_count;
1351 abstract_pkg_t **provides = pkg->provides;
1353 pkg->parent->state_flag |= SF_MARKED;
1354 for (i = 0; i < provides_count; i++) {
1355 provides[i]->state_flag |= SF_MARKED;
1360 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1362 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1364 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1366 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1369 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1371 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1374 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1376 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1379 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1381 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1384 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1388 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1389 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1392 pkg_info_preinstall_check(conf);
1394 if (conf->query_all)
1395 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1397 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1398 for (i = 0; i < argc; i++) {
1399 const char *target = argv[i];
1402 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1404 for (j = 0; j < available_pkgs->len; j++) {
1405 pkg_t *pkg = available_pkgs->pkgs[j];
1407 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1408 for (k = 0; k < count; k++) {
1409 abstract_pkg_t *apkg =
1410 ((what_field_type == WHATPROVIDES)
1412 : pkg->replaces[k]);
1413 if (fnmatch(target, apkg->name, 0) == 0) {
1414 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1415 if (strcmp(target, apkg->name) != 0)
1416 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1417 opkg_message(conf, OPKG_ERROR, "\n");
1422 pkg_vec_free(available_pkgs);
1427 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1429 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1432 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1434 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1437 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1441 pkg_vec_t *installed;
1443 str_list_t *installed_files;
1444 str_list_elt_t *iter;
1445 char *installed_file;
1451 installed = pkg_vec_alloc();
1452 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1453 pkg_vec_sort(installed, pkg_compare_names);
1455 for (i=0; i < installed->len; i++) {
1456 pkg = installed->pkgs[i];
1458 installed_files = pkg_get_installed_files(pkg);
1460 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1461 installed_file = (char *)iter->data;
1462 if (fnmatch(argv[0], installed_file, 0)==0) {
1463 if (opkg_cb_list) opkg_cb_list(pkg->name,
1465 pkg_version_str_alloc(pkg),
1466 pkg->state_status, p_userdata);
1470 pkg_free_installed_files(pkg);
1473 pkg_vec_free(installed);
1478 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1481 /* this is a bit gross */
1483 parseVersion(&p1, argv[0]);
1484 parseVersion(&p2, argv[2]);
1485 return pkg_version_satisfied(&p1, &p2, argv[1]);
1487 opkg_message(conf, OPKG_ERROR,
1488 "opkg compare_versions <v1> <op> <v2>\n"
1489 "<op> is one of <= >= << >> =\n");
1494 #ifndef HOST_CPU_STR
1495 #define HOST_CPU_STR__(X) #X
1496 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1497 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1500 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1502 nv_pair_list_elt_t *l;
1504 list_for_each_entry(l, &conf->arch_list.head, node) {
1505 nv_pair_t *nv = (nv_pair_t *)l->data;
1506 printf("arch %s %s\n", nv->name, nv->value);