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);
256 err = opkg_download(conf, url, list_file_name, NULL, NULL);
260 opkg_message(conf, OPKG_NOTICE,
261 "Updated list of available packages in %s\n",
265 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
266 if (conf->check_signature) {
267 /* download detached signitures to verify the package lists */
268 /* get the url for the sig file */
269 if (src->extra_data) /* debian style? */
270 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
273 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
275 /* create temporary file for it */
278 /* Put the signature in the right place */
279 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
281 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
284 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
287 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
289 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
291 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
293 /* We shouldn't unlink the signature ! */
294 // unlink (tmp_file_name);
295 free (tmp_file_name);
301 free(list_file_name);
311 struct opkg_intercept
317 typedef struct opkg_intercept *opkg_intercept_t;
319 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
321 opkg_intercept_t ctx;
326 ctx = calloc (1, sizeof (*ctx));
327 oldpath = getenv ("PATH");
329 ctx->oldpath = strdup (oldpath);
335 sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
336 setenv ("PATH", newpath, 1);
341 sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
342 if (mkdir (ctx->statedir, 0770) < 0) {
343 if (errno == EEXIST) {
344 free (ctx->statedir);
348 perror (ctx->statedir);
351 setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
355 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
362 setenv ("PATH", ctx->oldpath, 1);
368 dir = opendir (ctx->statedir);
371 while (de = readdir (dir), de != NULL) {
374 if (de->d_name[0] == '.')
377 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
378 if (access (path, X_OK) == 0) {
388 perror (ctx->statedir);
390 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
394 free (ctx->statedir);
400 /* For package pkg do the following: If it is already visited, return. If not,
401 add it in visited list and recurse to its deps. Finally, add it to ordered
403 pkg_vec all contains all available packages in repos.
404 pkg_vec visited contains packages already visited by this function, and is
405 used to end recursion and avoid an infinite loop on graph cycles.
406 pkg_vec ordered will finally contain the ordered set of packages.
408 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
409 pkg_vec_t *visited, pkg_vec_t *ordered)
414 compound_depend_t * compound_depend;
415 depend_t ** possible_satisfiers;
416 abstract_pkg_t *abpkg;
417 abstract_pkg_t **dependents;
419 /* If it's just an available package, that is, not installed and not even
421 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
422 would do here. However, if there is an intermediate node (pkg) that is
423 configured and installed between two unpacked packages, the latter
424 won't be properly reordered, unless all installed/unpacked pkgs are
426 if (pkg->state_status == SS_NOT_INSTALLED)
429 /* If the package has already been visited (by this function), skip it */
430 for(j = 0; j < visited->len; j++)
431 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
432 opkg_message(conf, OPKG_INFO,
433 " pkg: %s already visited\n", pkg->name);
437 pkg_vec_insert(visited, pkg);
439 count = pkg->pre_depends_count + pkg->depends_count + \
440 pkg->recommends_count + pkg->suggests_count;
442 opkg_message(conf, OPKG_INFO,
443 " pkg: %s\n", pkg->name);
445 /* Iterate over all the dependencies of pkg. For each one, find a package
446 that is either installed or unpacked and satisfies this dependency.
447 (there should only be one such package per dependency installed or
448 unpacked). Then recurse to the dependency package */
449 for (j=0; j < count ; j++) {
450 compound_depend = &pkg->depends[j];
451 possible_satisfiers = compound_depend->possibilities;
452 for (k=0; k < compound_depend->possibility_count ; k++) {
453 abpkg = possible_satisfiers[k]->pkg;
454 dependents = abpkg->provided_by->pkgs;
456 if (dependents != NULL)
457 while (dependents [l] != NULL && l < abpkg->provided_by->len) {
458 opkg_message(conf, OPKG_INFO,
459 " Descending on pkg: %s\n",
460 dependents [l]->name);
462 /* find whether dependent l is installed or unpacked,
463 * and then find which package in the list satisfies it */
464 for(m = 0; m < all->len; m++) {
466 if ( dep->state_status != SS_NOT_INSTALLED)
467 if ( ! strcmp(dep->name, dependents[l]->name)) {
468 opkg_recurse_pkgs_in_order(conf, dep, all,
470 /* Stop the outer loop */
471 l = abpkg->provided_by->len;
472 /* break from the inner loop */
481 /* When all recursions from this node down, are over, and all
482 dependencies have been added in proper order in the ordered array, add
483 also the package pkg to ordered array */
484 pkg_vec_insert(ordered, pkg);
490 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
492 pkg_vec_t *all, *ordered, *visited;
498 opkg_message(conf, OPKG_INFO,
499 "Configuring unpacked packages\n");
502 all = pkg_vec_alloc();
504 pkg_hash_fetch_available(&conf->pkg_hash, all);
506 /* Reorder pkgs in order to be configured according to the Depends: tag
508 opkg_message(conf, OPKG_INFO,
509 "Reordering packages before configuring them...\n");
510 ordered = pkg_vec_alloc();
511 visited = pkg_vec_alloc();
512 for(i = 0; i < all->len; i++) {
514 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
518 ic = opkg_prep_intercepts (conf);
520 for(i = 0; i < all->len; i++) {
523 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
526 if (pkg->state_status == SS_UNPACKED) {
527 opkg_message(conf, OPKG_NOTICE,
528 "Configuring %s\n", pkg->name);
530 r = opkg_configure(conf, pkg);
532 pkg->state_status = SS_INSTALLED;
533 pkg->parent->state_status = SS_INSTALLED;
534 pkg->state_flag &= ~SF_PREFER;
542 r = opkg_finalize_intercepts (ic);
547 pkg_vec_free(ordered);
548 pkg_vec_free(visited);
553 static opkg_conf_t *global_conf;
555 static void sigint_handler(int sig)
557 signal(sig, SIG_DFL);
558 opkg_message(NULL, OPKG_NOTICE,
559 "opkg: interrupted. writing out status database\n");
560 write_status_files_if_changed(global_conf);
564 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
571 signal(SIGINT, sigint_handler);
574 * Now scan through package names and install
576 for (i=0; i < argc; i++) {
579 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
580 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
581 if (err != EINVAL && err != 0)
584 pkg_info_preinstall_check(conf);
586 for (i=0; i < argc; i++) {
588 err = opkg_install_by_name(conf, arg);
589 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
590 opkg_message(conf, OPKG_ERROR,
591 "Cannot find package %s.\n",
596 /* recheck to verify that all dependences are satisfied */
597 if (0) opkg_satisfy_all_dependences(conf);
599 opkg_configure_packages(conf, NULL);
601 write_status_files_if_changed(conf);
606 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
613 signal(SIGINT, sigint_handler);
616 for (i=0; i < argc; i++) {
619 err = opkg_prepare_url_for_install(conf, arg, &arg);
620 if (err != EINVAL && err != 0)
623 pkg_info_preinstall_check(conf);
625 for (i=0; i < argc; i++) {
627 if (conf->restrict_to_default_dest) {
628 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
632 opkg_message(conf, OPKG_NOTICE,
633 "Package %s not installed in %s\n",
634 argv[i], conf->default_dest->name);
638 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
642 opkg_upgrade_pkg(conf, pkg);
644 opkg_install_by_name(conf, arg);
648 pkg_vec_t *installed = pkg_vec_alloc();
650 pkg_info_preinstall_check(conf);
652 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
653 for (i = 0; i < installed->len; i++) {
654 pkg = installed->pkgs[i];
655 opkg_upgrade_pkg(conf, pkg);
657 pkg_vec_free(installed);
660 /* recheck to verify that all dependences are satisfied */
661 if (0) opkg_satisfy_all_dependences(conf);
663 opkg_configure_packages(conf, NULL);
665 write_status_files_if_changed(conf);
670 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
676 pkg_info_preinstall_check(conf);
677 for (i = 0; i < argc; i++) {
680 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
682 opkg_message(conf, OPKG_ERROR,
683 "Cannot find package %s.\n"
684 "Check the spelling or perhaps run 'opkg update'\n",
689 err = opkg_download_pkg(conf, pkg, ".");
692 opkg_message(conf, OPKG_ERROR,
693 "Failed to download %s\n", pkg->name);
695 opkg_message(conf, OPKG_NOTICE,
696 "Downloaded %s as %s\n",
697 pkg->name, pkg->local_filename);
705 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
708 pkg_vec_t *available;
710 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
712 char *pkg_name = NULL;
718 available = pkg_vec_alloc();
719 pkg_hash_fetch_available(&conf->pkg_hash, available);
720 pkg_vec_sort(available, pkg_compare_names);
721 for (i=0; i < available->len; i++) {
722 pkg = available->pkgs[i];
723 /* if we have package name or pattern and pkg does not match, then skip it */
724 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
726 if (pkg->description) {
727 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
729 desc_short[0] = '\0';
731 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
732 newline = strchr(desc_short, '\n');
737 version_str = pkg_version_str_alloc(pkg);
738 opkg_cb_list(pkg->name,desc_short,
745 pkg_vec_free(available);
751 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
754 pkg_vec_t *available;
756 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
758 char *pkg_name = NULL;
764 available = pkg_vec_alloc();
765 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
766 pkg_vec_sort(available, pkg_compare_names);
767 for (i=0; i < available->len; i++) {
768 pkg = available->pkgs[i];
769 /* if we have package name or pattern and pkg does not match, then skip it */
770 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
772 if (pkg->description) {
773 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
775 desc_short[0] = '\0';
777 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
778 newline = strchr(desc_short, '\n');
783 version_str = pkg_version_str_alloc(pkg);
784 opkg_cb_list(pkg->name,desc_short,
792 pkg_vec_free(available);
797 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
799 struct active_list *head = prepare_upgrade_list(conf);
800 struct active_list *node=NULL;
801 pkg_t *_old_pkg, *_new_pkg;
803 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
804 _old_pkg = list_entry(node, pkg_t, list);
805 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
806 old_v = pkg_version_str_alloc(_old_pkg);
807 new_v = pkg_version_str_alloc(_new_pkg);
809 opkg_cb_list(_old_pkg->name, new_v, old_v, _old_pkg->state_status, p_userdata);
813 active_list_head_delete(head);
817 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
820 pkg_vec_t *available;
822 char *pkg_name = NULL;
823 char **pkg_fields = NULL;
831 pkg_fields = &argv[1];
835 available = pkg_vec_alloc();
837 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
839 pkg_hash_fetch_available(&conf->pkg_hash, available);
840 for (i=0; i < available->len; i++) {
841 pkg = available->pkgs[i];
842 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
846 buff = pkg_formatted_info(pkg);
848 if (opkg_cb_status) opkg_cb_status(pkg->name,
853 We should not forget that actually the pointer is allocated.
854 We need to free it :) ( Thanks florian for seeing the error )
859 if (conf->verbosity > 1) {
860 conffile_list_elt_t *iter;
861 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
862 conffile_t *cf = (conffile_t *)iter->data;
863 int modified = conffile_has_been_modified(conf, cf);
864 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
865 cf->name, cf->value, modified);
869 pkg_vec_free(available);
874 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
876 return opkg_info_status_cmd(conf, argc, argv, 0);
879 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
881 return opkg_info_status_cmd(conf, argc, argv, 1);
884 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
889 char *pkg_name = NULL;
893 err = opkg_configure_packages (conf, pkg_name);
896 err = opkg_configure_packages (conf, NULL);
899 write_status_files_if_changed(conf);
904 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
910 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
911 err = glob(globpattern, 0, NULL, &globbuf);
917 opkg_message(conf, OPKG_NOTICE,
918 "The following packages in %s will now be installed.\n",
920 for (i = 0; i < globbuf.gl_pathc; i++) {
921 opkg_message(conf, OPKG_NOTICE,
922 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
924 opkg_message(conf, OPKG_NOTICE, "\n");
925 for (i = 0; i < globbuf.gl_pathc; i++) {
926 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
928 err = unlink(globbuf.gl_pathv[i]);
930 opkg_message(conf, OPKG_ERROR,
931 "%s: ERROR: failed to unlink %s: %s\n",
932 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
942 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
946 pkg_t *pkg_to_remove;
947 pkg_vec_t *available;
948 char *pkg_name = NULL;
950 signal(SIGINT, sigint_handler);
952 // ENH: Add the "no pkg removed" just in case.
956 pkg_info_preinstall_check(conf);
958 available = pkg_vec_alloc();
959 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
960 for (i=0; i < argc; i++) {
961 pkg_name = calloc(1, strlen(argv[i])+2);
962 strcpy(pkg_name,argv[i]);
963 for (a=0; a < available->len; a++) {
964 pkg = available->pkgs[a];
965 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
968 if (conf->restrict_to_default_dest) {
969 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
973 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
977 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
980 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
981 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
984 opkg_remove_pkg(conf, pkg_to_remove,0);
989 pkg_vec_free(available);
991 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
993 int flagged_pkg_count = 0;
996 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
998 for (i = 0; i < installed_pkgs->len; i++) {
999 pkg_t *pkg = installed_pkgs->pkgs[i];
1000 if (pkg->state_flag & SF_USER) {
1001 flagged_pkg_count++;
1003 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
1004 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
1007 if (!flagged_pkg_count) {
1008 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
1009 "so refusing to uninstall unflagged non-leaf packages\n");
1013 /* find packages not flagged SF_USER (i.e., installed to
1014 * satisfy a dependence) and not having any dependents, and
1018 for (i = 0; i < installed_pkgs->len; i++) {
1019 pkg_t *pkg = installed_pkgs->pkgs[i];
1020 if (!(pkg->state_flag & SF_USER)
1021 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1023 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1024 opkg_remove_pkg(conf, pkg,0);
1029 pkg_vec_free(installed_pkgs);
1033 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1035 write_status_files_if_changed(conf);
1039 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1045 signal(SIGINT, sigint_handler);
1047 pkg_info_preinstall_check(conf);
1049 for (i=0; i < argc; i++) {
1050 if (conf->restrict_to_default_dest) {
1051 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1053 conf->default_dest);
1055 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1059 opkg_message(conf, OPKG_ERROR,
1060 "Package %s is not installed.\n", argv[i]);
1063 opkg_purge_pkg(conf, pkg);
1066 write_status_files_if_changed(conf);
1070 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1074 const char *flags = argv[0];
1077 signal(SIGINT, sigint_handler);
1079 for (i=1; i < argc; i++) {
1080 if (conf->restrict_to_default_dest) {
1081 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1083 conf->default_dest);
1085 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1089 opkg_message(conf, OPKG_ERROR,
1090 "Package %s is not installed.\n", argv[i]);
1093 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1094 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1095 pkg->state_flag = pkg_state_flag_from_str(flags);
1097 /* pb_ asked this feature 03292004 */
1098 /* Actually I will use only this two, but this is an open for various status */
1099 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1100 pkg->state_status = pkg_state_status_from_str(flags);
1102 opkg_state_changed++;
1103 opkg_message(conf, OPKG_NOTICE,
1104 "Setting flags for package %s to %s\n",
1108 write_status_files_if_changed(conf);
1112 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1115 str_list_t *installed_files;
1116 str_list_elt_t *iter;
1118 size_t buff_len = 8192;
1122 buff = (char *)calloc(1, buff_len);
1123 if ( buff == NULL ) {
1124 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1132 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1135 opkg_message(conf, OPKG_ERROR,
1136 "Package %s not installed.\n", argv[0]);
1140 installed_files = pkg_get_installed_files(pkg);
1141 pkg_version = pkg_version_str_alloc(pkg);
1145 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1146 pkg->name, pkg_version, pkg->dest->name) + 1;
1147 if (used_len > buff_len) {
1149 buff = realloc (buff, buff_len);
1152 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1153 used_len += strlen (iter->data) + 1;
1154 while (buff_len <= used_len) {
1156 buff = realloc (buff, buff_len);
1158 strncat(buff, iter->data, buff_len);
1159 strncat(buff, "\n", buff_len);
1161 if (opkg_cb_list) opkg_cb_list(pkg->name,
1163 pkg_version_str_alloc(pkg),
1170 pkg_free_installed_files(pkg);
1175 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1179 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1180 const char *rel_str = "depends on";
1183 pkg_info_preinstall_check(conf);
1185 if (conf->query_all)
1186 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1188 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1189 for (i = 0; i < argc; i++) {
1190 const char *target = argv[i];
1193 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1195 for (j = 0; j < available_pkgs->len; j++) {
1196 pkg_t *pkg = available_pkgs->pkgs[j];
1197 if (fnmatch(target, pkg->name, 0) == 0) {
1199 int count = pkg->depends_count + pkg->pre_depends_count;
1200 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1201 target, pkg->architecture, rel_str);
1202 for (k = 0; k < count; k++) {
1203 compound_depend_t *cdepend = &pkg->depends[k];
1205 for (l = 0; l < cdepend->possibility_count; l++) {
1206 depend_t *possibility = cdepend->possibilities[l];
1207 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1208 if (conf->verbosity > 0) {
1209 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1210 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1211 if (possibility->version) {
1212 char *typestr = NULL;
1213 switch (possibility->constraint) {
1214 case NONE: typestr = "none"; break;
1215 case EARLIER: typestr = "<"; break;
1216 case EARLIER_EQUAL: typestr = "<="; break;
1217 case EQUAL: typestr = "="; break;
1218 case LATER_EQUAL: typestr = ">="; break;
1219 case LATER: typestr = ">"; break;
1221 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1225 opkg_message(conf, OPKG_ERROR, "\n");
1231 pkg_vec_free(available_pkgs);
1236 enum what_field_type {
1245 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1249 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1250 const char *rel_str = NULL;
1254 switch (what_field_type) {
1255 case WHATDEPENDS: rel_str = "depends on"; break;
1256 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1257 case WHATSUGGESTS: rel_str = "suggests"; break;
1258 case WHATRECOMMENDS: rel_str = "recommends"; break;
1259 case WHATPROVIDES: rel_str = "provides"; break;
1260 case WHATREPLACES: rel_str = "replaces"; break;
1263 if (conf->query_all)
1264 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1266 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1268 /* mark the root set */
1269 pkg_vec_clear_marks(available_pkgs);
1270 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1271 for (i = 0; i < argc; i++) {
1272 const char *dependee_pattern = argv[i];
1273 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1275 for (i = 0; i < available_pkgs->len; i++) {
1276 pkg_t *pkg = available_pkgs->pkgs[i];
1277 if (pkg->state_flag & SF_MARKED) {
1278 /* mark the parent (abstract) package */
1279 pkg_mark_provides(pkg);
1280 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1284 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1289 for (j = 0; j < available_pkgs->len; j++) {
1290 pkg_t *pkg = available_pkgs->pkgs[j];
1292 int count = ((what_field_type == WHATCONFLICTS)
1293 ? pkg->conflicts_count
1294 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1295 /* skip this package if it is already marked */
1296 if (pkg->parent->state_flag & SF_MARKED) {
1299 for (k = 0; k < count; k++) {
1300 compound_depend_t *cdepend =
1301 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1303 for (l = 0; l < cdepend->possibility_count; l++) {
1304 depend_t *possibility = cdepend->possibilities[l];
1305 if (possibility->pkg->state_flag & SF_MARKED) {
1306 /* mark the depending package so we won't visit it again */
1307 pkg->state_flag |= SF_MARKED;
1308 pkg_mark_provides(pkg);
1311 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1312 if (conf->verbosity > 0) {
1313 char *ver = pkg_version_str_alloc(pkg);
1314 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1315 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1316 if (possibility->version) {
1317 char *typestr = NULL;
1318 switch (possibility->constraint) {
1319 case NONE: typestr = "none"; break;
1320 case EARLIER: typestr = "<"; break;
1321 case EARLIER_EQUAL: typestr = "<="; break;
1322 case EQUAL: typestr = "="; break;
1323 case LATER_EQUAL: typestr = ">="; break;
1324 case LATER: typestr = ">"; break;
1326 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1329 if (!pkg_dependence_satisfiable(conf, possibility))
1330 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1332 opkg_message(conf, OPKG_NOTICE, "\n");
1340 } while (changed && recursive);
1341 pkg_vec_free(available_pkgs);
1347 static int pkg_mark_provides(pkg_t *pkg)
1349 int provides_count = pkg->provides_count;
1350 abstract_pkg_t **provides = pkg->provides;
1352 pkg->parent->state_flag |= SF_MARKED;
1353 for (i = 0; i < provides_count; i++) {
1354 provides[i]->state_flag |= SF_MARKED;
1359 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1361 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1363 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1365 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1368 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1370 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1373 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1375 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1378 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1380 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1383 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1387 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1388 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1391 pkg_info_preinstall_check(conf);
1393 if (conf->query_all)
1394 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1396 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1397 for (i = 0; i < argc; i++) {
1398 const char *target = argv[i];
1401 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1403 for (j = 0; j < available_pkgs->len; j++) {
1404 pkg_t *pkg = available_pkgs->pkgs[j];
1406 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1407 for (k = 0; k < count; k++) {
1408 abstract_pkg_t *apkg =
1409 ((what_field_type == WHATPROVIDES)
1411 : pkg->replaces[k]);
1412 if (fnmatch(target, apkg->name, 0) == 0) {
1413 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1414 if (strcmp(target, apkg->name) != 0)
1415 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1416 opkg_message(conf, OPKG_ERROR, "\n");
1421 pkg_vec_free(available_pkgs);
1426 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1428 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1431 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1433 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1436 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1440 pkg_vec_t *installed;
1442 str_list_t *installed_files;
1443 str_list_elt_t *iter;
1444 char *installed_file;
1450 installed = pkg_vec_alloc();
1451 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1452 pkg_vec_sort(installed, pkg_compare_names);
1454 for (i=0; i < installed->len; i++) {
1455 pkg = installed->pkgs[i];
1457 installed_files = pkg_get_installed_files(pkg);
1459 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1460 installed_file = (char *)iter->data;
1461 if (fnmatch(argv[0], installed_file, 0)==0) {
1462 if (opkg_cb_list) opkg_cb_list(pkg->name,
1464 pkg_version_str_alloc(pkg),
1465 pkg->state_status, p_userdata);
1469 pkg_free_installed_files(pkg);
1472 pkg_vec_free(installed);
1477 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1480 /* this is a bit gross */
1482 parseVersion(&p1, argv[0]);
1483 parseVersion(&p2, argv[2]);
1484 return pkg_version_satisfied(&p1, &p2, argv[1]);
1486 opkg_message(conf, OPKG_ERROR,
1487 "opkg compare_versions <v1> <op> <v2>\n"
1488 "<op> is one of <= >= << >> =\n");
1493 #ifndef HOST_CPU_STR
1494 #define HOST_CPU_STR__(X) #X
1495 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1496 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1499 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1501 nv_pair_list_elt_t *l;
1503 list_for_each_entry(l, &conf->arch_list.head, node) {
1504 nv_pair_t *nv = (nv_pair_t *)l->data;
1505 printf("arch %s %s\n", nv->name, nv->value);