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)
147 reverse_error_list(&error_list);
149 printf ("Collected errors:\n");
150 /* Here we print the errors collected and free the list */
151 while (error_list != NULL) {
152 printf (" * %s", error_list->errmsg);
153 error_list = error_list->next;
161 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
164 p_userdata = userdata;
167 result = (cmd->fun)(conf, argc, argv);
169 if ( result != 0 && !error_list) {
170 opkg_message(conf, OPKG_NOTICE, "An error occurred, return value: %d.\n", result);
173 opkg_print_error_list (conf);
179 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
185 pkg_src_list_elt_t *iter;
189 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
191 if (! file_is_dir(lists_dir)) {
192 if (file_exists(lists_dir)) {
193 opkg_message(conf, OPKG_ERROR,
194 "%s: ERROR: %s exists, but is not a directory\n",
195 __FUNCTION__, lists_dir);
199 err = file_mkdir_hier(lists_dir, 0755);
201 opkg_message(conf, OPKG_ERROR,
202 "%s: ERROR: failed to make directory %s: %s\n",
203 __FUNCTION__, lists_dir, strerror(errno));
212 tmp = strdup ("/tmp/opkg.XXXXXX");
214 if (mkdtemp (tmp) == NULL) {
220 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
221 char *url, *list_file_name;
223 src = (pkg_src_t *)iter->data;
225 if (src->extra_data) /* debian style? */
226 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
227 src->gzip ? "Packages.gz" : "Packages");
229 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
231 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
236 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
237 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
239 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
240 in = fopen (tmp_file_name, "r");
241 out = fopen (list_file_name, "w");
250 unlink (tmp_file_name);
253 err = opkg_download(conf, url, list_file_name, NULL, NULL);
257 opkg_message(conf, OPKG_NOTICE,
258 "Updated list of available packages in %s\n",
264 if (conf->check_signature) {
265 /* download detached signitures to verify the package lists */
266 /* get the url for the sig file */
267 if (src->extra_data) /* debian style? */
268 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
271 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
273 /* create temporary file for it */
276 sprintf_alloc (&tmp_file_name, "%s/%s", tmp, "Packages.sig");
278 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
281 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
284 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
286 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
288 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
290 unlink (tmp_file_name);
291 free (tmp_file_name);
297 free(list_file_name);
307 struct opkg_intercept
313 typedef struct opkg_intercept *opkg_intercept_t;
315 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
317 opkg_intercept_t ctx;
322 ctx = calloc (1, sizeof (*ctx));
323 oldpath = getenv ("PATH");
325 ctx->oldpath = strdup (oldpath);
331 sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
332 setenv ("PATH", newpath, 1);
337 sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
338 if (mkdir (ctx->statedir, 0770) < 0) {
339 if (errno == EEXIST) {
340 free (ctx->statedir);
344 perror (ctx->statedir);
347 setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
351 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
358 setenv ("PATH", ctx->oldpath, 1);
364 dir = opendir (ctx->statedir);
367 while (de = readdir (dir), de != NULL) {
370 if (de->d_name[0] == '.')
373 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
374 if (access (path, X_OK) == 0) {
384 perror (ctx->statedir);
386 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
390 free (ctx->statedir);
396 /* For package pkg do the following: If it is already visited, return. If not,
397 add it in visited list and recurse to its deps. Finally, add it to ordered
399 pkg_vec all contains all available packages in repos.
400 pkg_vec visited contains packages already visited by this function, and is
401 used to end recursion and avoid an infinite loop on graph cycles.
402 pkg_vec ordered will finally contain the ordered set of packages.
404 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
405 pkg_vec_t *visited, pkg_vec_t *ordered)
410 compound_depend_t * compound_depend;
411 depend_t ** possible_satisfiers;
412 abstract_pkg_t *abpkg;
413 abstract_pkg_t **dependents;
415 /* If it's just an available package, that is, not installed and not even
417 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
418 would do here. However, if there is an intermediate node (pkg) that is
419 configured and installed between two unpacked packages, the latter
420 won't be properly reordered, unless all installed/unpacked pkgs are
422 if (pkg->state_status == SS_NOT_INSTALLED)
425 /* If the package has already been visited (by this function), skip it */
426 for(j = 0; j < visited->len; j++)
427 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
428 opkg_message(conf, OPKG_INFO,
429 " pkg: %s already visited\n", pkg->name);
433 pkg_vec_insert(visited, pkg);
435 count = pkg->pre_depends_count + pkg->depends_count + \
436 pkg->recommends_count + pkg->suggests_count;
438 opkg_message(conf, OPKG_INFO,
439 " pkg: %s\n", pkg->name);
441 /* Iterate over all the dependencies of pkg. For each one, find a package
442 that is either installed or unpacked and satisfies this dependency.
443 (there should only be one such package per dependency installed or
444 unpacked). Then recurse to the dependency package */
445 for (j=0; j < count ; j++) {
446 compound_depend = &pkg->depends[j];
447 possible_satisfiers = compound_depend->possibilities;
448 for (k=0; k < compound_depend->possibility_count ; k++) {
449 abpkg = possible_satisfiers[k]->pkg;
450 dependents = abpkg->provided_by->pkgs;
452 if (dependents != NULL)
453 while (dependents [l] != NULL && l < abpkg->provided_by->len) {
454 opkg_message(conf, OPKG_INFO,
455 " Descending on pkg: %s\n",
456 dependents [l]->name);
458 /* find whether dependent l is installed or unpacked,
459 * and then find which package in the list satisfies it */
460 for(m = 0; m < all->len; m++) {
462 if ( dep->state_status != SS_NOT_INSTALLED)
463 if ( ! strcmp(dep->name, dependents[l]->name)) {
464 opkg_recurse_pkgs_in_order(conf, dep, all,
466 /* Stop the outer loop */
467 l = abpkg->provided_by->len;
468 /* break from the inner loop */
477 /* When all recursions from this node down, are over, and all
478 dependencies have been added in proper order in the ordered array, add
479 also the package pkg to ordered array */
480 pkg_vec_insert(ordered, pkg);
486 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
488 pkg_vec_t *all, *ordered, *visited;
494 opkg_message(conf, OPKG_INFO,
495 "Configuring unpacked packages\n");
498 all = pkg_vec_alloc();
500 pkg_hash_fetch_available(&conf->pkg_hash, all);
502 /* Reorder pkgs in order to be configured according to the Depends: tag
504 opkg_message(conf, OPKG_INFO,
505 "Reordering packages before configuring them...\n");
506 ordered = pkg_vec_alloc();
507 visited = pkg_vec_alloc();
508 for(i = 0; i < all->len; i++) {
510 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
514 ic = opkg_prep_intercepts (conf);
516 for(i = 0; i < all->len; i++) {
519 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
522 if (pkg->state_status == SS_UNPACKED) {
523 opkg_message(conf, OPKG_NOTICE,
524 "Configuring %s\n", pkg->name);
526 r = opkg_configure(conf, pkg);
528 pkg->state_status = SS_INSTALLED;
529 pkg->parent->state_status = SS_INSTALLED;
530 pkg->state_flag &= ~SF_PREFER;
538 r = opkg_finalize_intercepts (ic);
543 pkg_vec_free(ordered);
544 pkg_vec_free(visited);
549 static opkg_conf_t *global_conf;
551 static void sigint_handler(int sig)
553 signal(sig, SIG_DFL);
554 opkg_message(NULL, OPKG_NOTICE,
555 "opkg: interrupted. writing out status database\n");
556 write_status_files_if_changed(global_conf);
560 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
567 signal(SIGINT, sigint_handler);
570 * Now scan through package names and install
572 for (i=0; i < argc; i++) {
575 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
576 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
577 if (err != EINVAL && err != 0)
580 pkg_info_preinstall_check(conf);
582 for (i=0; i < argc; i++) {
584 err = opkg_install_by_name(conf, arg);
585 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
586 opkg_message(conf, OPKG_ERROR,
587 "Cannot find package %s.\n",
592 /* recheck to verify that all dependences are satisfied */
593 if (0) opkg_satisfy_all_dependences(conf);
595 opkg_configure_packages(conf, NULL);
597 write_status_files_if_changed(conf);
602 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
609 signal(SIGINT, sigint_handler);
612 for (i=0; i < argc; i++) {
615 err = opkg_prepare_url_for_install(conf, arg, &arg);
616 if (err != EINVAL && err != 0)
619 pkg_info_preinstall_check(conf);
621 for (i=0; i < argc; i++) {
623 if (conf->restrict_to_default_dest) {
624 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
628 opkg_message(conf, OPKG_NOTICE,
629 "Package %s not installed in %s\n",
630 argv[i], conf->default_dest->name);
634 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
638 opkg_upgrade_pkg(conf, pkg);
640 opkg_install_by_name(conf, arg);
644 pkg_vec_t *installed = pkg_vec_alloc();
646 pkg_info_preinstall_check(conf);
648 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
649 for (i = 0; i < installed->len; i++) {
650 pkg = installed->pkgs[i];
651 opkg_upgrade_pkg(conf, pkg);
653 pkg_vec_free(installed);
656 /* recheck to verify that all dependences are satisfied */
657 if (0) opkg_satisfy_all_dependences(conf);
659 opkg_configure_packages(conf, NULL);
661 write_status_files_if_changed(conf);
666 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
672 pkg_info_preinstall_check(conf);
673 for (i = 0; i < argc; i++) {
676 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
678 opkg_message(conf, OPKG_ERROR,
679 "Cannot find package %s.\n"
680 "Check the spelling or perhaps run 'opkg update'\n",
685 err = opkg_download_pkg(conf, pkg, ".");
688 opkg_message(conf, OPKG_ERROR,
689 "Failed to download %s\n", pkg->name);
691 opkg_message(conf, OPKG_NOTICE,
692 "Downloaded %s as %s\n",
693 pkg->name, pkg->local_filename);
701 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
704 pkg_vec_t *available;
706 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
708 char *pkg_name = NULL;
714 available = pkg_vec_alloc();
715 pkg_hash_fetch_available(&conf->pkg_hash, available);
716 pkg_vec_sort(available, pkg_compare_names);
717 for (i=0; i < available->len; i++) {
718 pkg = available->pkgs[i];
719 /* if we have package name or pattern and pkg does not match, then skip it */
720 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
722 if (pkg->description) {
723 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
725 desc_short[0] = '\0';
727 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
728 newline = strchr(desc_short, '\n');
733 version_str = pkg_version_str_alloc(pkg);
734 opkg_cb_list(pkg->name,desc_short,
741 pkg_vec_free(available);
747 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
750 pkg_vec_t *available;
752 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
754 char *pkg_name = NULL;
760 available = pkg_vec_alloc();
761 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
762 pkg_vec_sort(available, pkg_compare_names);
763 for (i=0; i < available->len; i++) {
764 pkg = available->pkgs[i];
765 /* if we have package name or pattern and pkg does not match, then skip it */
766 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
768 if (pkg->description) {
769 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
771 desc_short[0] = '\0';
773 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
774 newline = strchr(desc_short, '\n');
779 version_str = pkg_version_str_alloc(pkg);
780 opkg_cb_list(pkg->name,desc_short,
791 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
793 struct active_list *head = prepare_upgrade_list(conf);
794 struct active_list *node=NULL;
795 pkg_t *_old_pkg, *_new_pkg;
797 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
798 _old_pkg = list_entry(node, pkg_t, list);
799 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
800 old_v = pkg_version_str_alloc(_old_pkg);
801 new_v = pkg_version_str_alloc(_new_pkg);
803 opkg_cb_list(_old_pkg->name, new_v, old_v, _old_pkg->state_status, p_userdata);
807 active_list_head_delete(head);
811 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
814 pkg_vec_t *available;
816 char *pkg_name = NULL;
817 char **pkg_fields = NULL;
825 pkg_fields = &argv[1];
829 available = pkg_vec_alloc();
831 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
833 pkg_hash_fetch_available(&conf->pkg_hash, available);
834 for (i=0; i < available->len; i++) {
835 pkg = available->pkgs[i];
836 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
840 buff = pkg_formatted_info(pkg);
842 if (opkg_cb_status) opkg_cb_status(pkg->name,
847 We should not forget that actually the pointer is allocated.
848 We need to free it :) ( Thanks florian for seeing the error )
853 if (conf->verbosity > 1) {
854 conffile_list_elt_t *iter;
855 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
856 conffile_t *cf = (conffile_t *)iter->data;
857 int modified = conffile_has_been_modified(conf, cf);
858 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
859 cf->name, cf->value, modified);
863 pkg_vec_free(available);
868 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
870 return opkg_info_status_cmd(conf, argc, argv, 0);
873 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
875 return opkg_info_status_cmd(conf, argc, argv, 1);
878 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
883 char *pkg_name = NULL;
887 err = opkg_configure_packages (conf, pkg_name);
890 err = opkg_configure_packages (conf, NULL);
893 write_status_files_if_changed(conf);
898 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
904 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
905 err = glob(globpattern, 0, NULL, &globbuf);
911 opkg_message(conf, OPKG_NOTICE,
912 "The following packages in %s will now be installed.\n",
914 for (i = 0; i < globbuf.gl_pathc; i++) {
915 opkg_message(conf, OPKG_NOTICE,
916 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
918 opkg_message(conf, OPKG_NOTICE, "\n");
919 for (i = 0; i < globbuf.gl_pathc; i++) {
920 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
922 err = unlink(globbuf.gl_pathv[i]);
924 opkg_message(conf, OPKG_ERROR,
925 "%s: ERROR: failed to unlink %s: %s\n",
926 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
936 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
940 pkg_t *pkg_to_remove;
941 pkg_vec_t *available;
942 char *pkg_name = NULL;
944 signal(SIGINT, sigint_handler);
946 // ENH: Add the "no pkg removed" just in case.
950 pkg_info_preinstall_check(conf);
952 available = pkg_vec_alloc();
953 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
954 for (i=0; i < argc; i++) {
955 pkg_name = calloc(1, strlen(argv[i])+2);
956 strcpy(pkg_name,argv[i]);
957 for (a=0; a < available->len; a++) {
958 pkg = available->pkgs[a];
959 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
962 if (conf->restrict_to_default_dest) {
963 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
967 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
971 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
974 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
975 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
978 opkg_remove_pkg(conf, pkg_to_remove,0);
983 pkg_vec_free(available);
985 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
987 int flagged_pkg_count = 0;
990 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
992 for (i = 0; i < installed_pkgs->len; i++) {
993 pkg_t *pkg = installed_pkgs->pkgs[i];
994 if (pkg->state_flag & SF_USER) {
997 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
998 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
1001 if (!flagged_pkg_count) {
1002 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
1003 "so refusing to uninstall unflagged non-leaf packages\n");
1007 /* find packages not flagged SF_USER (i.e., installed to
1008 * satisfy a dependence) and not having any dependents, and
1012 for (i = 0; i < installed_pkgs->len; i++) {
1013 pkg_t *pkg = installed_pkgs->pkgs[i];
1014 if (!(pkg->state_flag & SF_USER)
1015 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1017 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1018 opkg_remove_pkg(conf, pkg,0);
1023 pkg_vec_free(installed_pkgs);
1027 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1029 write_status_files_if_changed(conf);
1033 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1039 signal(SIGINT, sigint_handler);
1041 pkg_info_preinstall_check(conf);
1043 for (i=0; i < argc; i++) {
1044 if (conf->restrict_to_default_dest) {
1045 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1047 conf->default_dest);
1049 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1053 opkg_message(conf, OPKG_ERROR,
1054 "Package %s is not installed.\n", argv[i]);
1057 opkg_purge_pkg(conf, pkg);
1060 write_status_files_if_changed(conf);
1064 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1068 const char *flags = argv[0];
1071 signal(SIGINT, sigint_handler);
1073 for (i=1; i < argc; i++) {
1074 if (conf->restrict_to_default_dest) {
1075 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1077 conf->default_dest);
1079 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1083 opkg_message(conf, OPKG_ERROR,
1084 "Package %s is not installed.\n", argv[i]);
1087 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1088 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1089 pkg->state_flag = pkg_state_flag_from_str(flags);
1091 /* pb_ asked this feature 03292004 */
1092 /* Actually I will use only this two, but this is an open for various status */
1093 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1094 pkg->state_status = pkg_state_status_from_str(flags);
1096 opkg_state_changed++;
1097 opkg_message(conf, OPKG_NOTICE,
1098 "Setting flags for package %s to %s\n",
1102 write_status_files_if_changed(conf);
1106 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1109 str_list_t *installed_files;
1110 str_list_elt_t *iter;
1112 size_t buff_len = 8192;
1116 buff = (char *)calloc(1, buff_len);
1117 if ( buff == NULL ) {
1118 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1126 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1129 opkg_message(conf, OPKG_ERROR,
1130 "Package %s not installed.\n", argv[0]);
1134 installed_files = pkg_get_installed_files(pkg);
1135 pkg_version = pkg_version_str_alloc(pkg);
1139 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1140 pkg->name, pkg_version, pkg->dest->name) + 1;
1141 if (used_len > buff_len) {
1143 buff = realloc (buff, buff_len);
1146 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1147 used_len += strlen (iter->data) + 1;
1148 while (buff_len <= used_len) {
1150 buff = realloc (buff, buff_len);
1152 strncat(buff, iter->data, buff_len);
1153 strncat(buff, "\n", buff_len);
1155 if (opkg_cb_list) opkg_cb_list(pkg->name,
1157 pkg_version_str_alloc(pkg),
1164 pkg_free_installed_files(pkg);
1169 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1173 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1174 const char *rel_str = "depends on";
1177 pkg_info_preinstall_check(conf);
1179 if (conf->query_all)
1180 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1182 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1183 for (i = 0; i < argc; i++) {
1184 const char *target = argv[i];
1187 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1189 for (j = 0; j < available_pkgs->len; j++) {
1190 pkg_t *pkg = available_pkgs->pkgs[j];
1191 if (fnmatch(target, pkg->name, 0) == 0) {
1193 int count = pkg->depends_count + pkg->pre_depends_count;
1194 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1195 target, pkg->architecture, rel_str);
1196 for (k = 0; k < count; k++) {
1197 compound_depend_t *cdepend = &pkg->depends[k];
1199 for (l = 0; l < cdepend->possibility_count; l++) {
1200 depend_t *possibility = cdepend->possibilities[l];
1201 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1202 if (conf->verbosity > 0) {
1203 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1204 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1205 if (possibility->version) {
1206 char *typestr = NULL;
1207 switch (possibility->constraint) {
1208 case NONE: typestr = "none"; break;
1209 case EARLIER: typestr = "<"; break;
1210 case EARLIER_EQUAL: typestr = "<="; break;
1211 case EQUAL: typestr = "="; break;
1212 case LATER_EQUAL: typestr = ">="; break;
1213 case LATER: typestr = ">"; break;
1215 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1219 opkg_message(conf, OPKG_ERROR, "\n");
1225 pkg_vec_free(available_pkgs);
1230 enum what_field_type {
1239 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1243 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1244 const char *rel_str = NULL;
1248 switch (what_field_type) {
1249 case WHATDEPENDS: rel_str = "depends on"; break;
1250 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1251 case WHATSUGGESTS: rel_str = "suggests"; break;
1252 case WHATRECOMMENDS: rel_str = "recommends"; break;
1253 case WHATPROVIDES: rel_str = "provides"; break;
1254 case WHATREPLACES: rel_str = "replaces"; break;
1257 if (conf->query_all)
1258 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1260 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1262 /* mark the root set */
1263 pkg_vec_clear_marks(available_pkgs);
1264 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1265 for (i = 0; i < argc; i++) {
1266 const char *dependee_pattern = argv[i];
1267 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1269 for (i = 0; i < available_pkgs->len; i++) {
1270 pkg_t *pkg = available_pkgs->pkgs[i];
1271 if (pkg->state_flag & SF_MARKED) {
1272 /* mark the parent (abstract) package */
1273 pkg_mark_provides(pkg);
1274 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1278 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1283 for (j = 0; j < available_pkgs->len; j++) {
1284 pkg_t *pkg = available_pkgs->pkgs[j];
1286 int count = ((what_field_type == WHATCONFLICTS)
1287 ? pkg->conflicts_count
1288 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1289 /* skip this package if it is already marked */
1290 if (pkg->parent->state_flag & SF_MARKED) {
1293 for (k = 0; k < count; k++) {
1294 compound_depend_t *cdepend =
1295 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1297 for (l = 0; l < cdepend->possibility_count; l++) {
1298 depend_t *possibility = cdepend->possibilities[l];
1299 if (possibility->pkg->state_flag & SF_MARKED) {
1300 /* mark the depending package so we won't visit it again */
1301 pkg->state_flag |= SF_MARKED;
1302 pkg_mark_provides(pkg);
1305 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1306 if (conf->verbosity > 0) {
1307 char *ver = pkg_version_str_alloc(pkg);
1308 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1309 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1310 if (possibility->version) {
1311 char *typestr = NULL;
1312 switch (possibility->constraint) {
1313 case NONE: typestr = "none"; break;
1314 case EARLIER: typestr = "<"; break;
1315 case EARLIER_EQUAL: typestr = "<="; break;
1316 case EQUAL: typestr = "="; break;
1317 case LATER_EQUAL: typestr = ">="; break;
1318 case LATER: typestr = ">"; break;
1320 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1323 if (!pkg_dependence_satisfiable(conf, possibility))
1324 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1326 opkg_message(conf, OPKG_NOTICE, "\n");
1334 } while (changed && recursive);
1335 pkg_vec_free(available_pkgs);
1341 static int pkg_mark_provides(pkg_t *pkg)
1343 int provides_count = pkg->provides_count;
1344 abstract_pkg_t **provides = pkg->provides;
1346 pkg->parent->state_flag |= SF_MARKED;
1347 for (i = 0; i < provides_count; i++) {
1348 provides[i]->state_flag |= SF_MARKED;
1353 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1355 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1357 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1359 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1362 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1364 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1367 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1369 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1372 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1374 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1377 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1381 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1382 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1385 pkg_info_preinstall_check(conf);
1387 if (conf->query_all)
1388 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1390 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1391 for (i = 0; i < argc; i++) {
1392 const char *target = argv[i];
1395 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1397 for (j = 0; j < available_pkgs->len; j++) {
1398 pkg_t *pkg = available_pkgs->pkgs[j];
1400 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1401 for (k = 0; k < count; k++) {
1402 abstract_pkg_t *apkg =
1403 ((what_field_type == WHATPROVIDES)
1405 : pkg->replaces[k]);
1406 if (fnmatch(target, apkg->name, 0) == 0) {
1407 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1408 if (strcmp(target, apkg->name) != 0)
1409 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1410 opkg_message(conf, OPKG_ERROR, "\n");
1415 pkg_vec_free(available_pkgs);
1420 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1422 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1425 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1427 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1430 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1434 pkg_vec_t *installed;
1436 str_list_t *installed_files;
1437 str_list_elt_t *iter;
1438 char *installed_file;
1444 installed = pkg_vec_alloc();
1445 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1446 pkg_vec_sort(installed, pkg_compare_names);
1448 for (i=0; i < installed->len; i++) {
1449 pkg = installed->pkgs[i];
1451 installed_files = pkg_get_installed_files(pkg);
1453 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1454 installed_file = (char *)iter->data;
1455 if (fnmatch(argv[0], installed_file, 0)==0) {
1456 if (opkg_cb_list) opkg_cb_list(pkg->name,
1458 pkg_version_str_alloc(pkg),
1459 pkg->state_status, p_userdata);
1463 pkg_free_installed_files(pkg);
1466 pkg_vec_free(installed);
1471 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1474 /* this is a bit gross */
1476 parseVersion(&p1, argv[0]);
1477 parseVersion(&p2, argv[2]);
1478 return pkg_version_satisfied(&p1, &p2, argv[1]);
1480 opkg_message(conf, OPKG_ERROR,
1481 "opkg compare_versions <v1> <op> <v2>\n"
1482 "<op> is one of <= >= << >> =\n");
1487 #ifndef HOST_CPU_STR
1488 #define HOST_CPU_STR__(X) #X
1489 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1490 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1493 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1495 nv_pair_list_elt_t *l;
1497 list_for_each_entry(l, &conf->arch_list.head, node) {
1498 nv_pair_t *nv = (nv_pair_t *)l->data;
1499 printf("arch %s %s\n", nv->name, nv->value);