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) {
383 perror (ctx->statedir);
385 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
389 free (ctx->statedir);
395 /* For package pkg do the following: If it is already visited, return. If not,
396 add it in visited list and recurse to its deps. Finally, add it to ordered
398 pkg_vec all contains all available packages in repos.
399 pkg_vec visited contains packages already visited by this function, and is
400 used to end recursion and avoid an infinite loop on graph cycles.
401 pkg_vec ordered will finally contain the ordered set of packages.
403 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
404 pkg_vec_t *visited, pkg_vec_t *ordered)
409 compound_depend_t * compound_depend;
410 depend_t ** possible_satisfiers;
411 abstract_pkg_t *abpkg;
412 abstract_pkg_t **dependents;
414 /* If it's just an available package, that is, not installed and not even
416 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
417 would do here. However, if there is an intermediate node (pkg) that is
418 configured and installed between two unpacked packages, the latter
419 won't be properly reordered, unless all installed/unpacked pkgs are
421 if (pkg->state_status == SS_NOT_INSTALLED)
424 /* If the package has already been visited (by this function), skip it */
425 for(j = 0; j < visited->len; j++)
426 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
427 opkg_message(conf, OPKG_INFO,
428 " pkg: %s already visited\n", pkg->name);
432 pkg_vec_insert(visited, pkg);
434 count = pkg->pre_depends_count + pkg->depends_count + \
435 pkg->recommends_count + pkg->suggests_count;
437 opkg_message(conf, OPKG_INFO,
438 " pkg: %s\n", pkg->name);
440 /* Iterate over all the dependencies of pkg. For each one, find a package
441 that is either installed or unpacked and satisfies this dependency.
442 (there should only be one such package per dependency installed or
443 unpacked). Then recurse to the dependency package */
444 for (j=0; j < count ; j++) {
445 compound_depend = &pkg->depends[j];
446 possible_satisfiers = compound_depend->possibilities;
447 for (k=0; k < compound_depend->possibility_count ; k++) {
448 abpkg = possible_satisfiers[k]->pkg;
449 dependents = abpkg->provided_by->pkgs;
451 if (dependents != NULL)
452 while (dependents [l] != NULL && l < abpkg->provided_by->len) {
453 opkg_message(conf, OPKG_INFO,
454 " Descending on pkg: %s\n",
455 dependents [l]->name);
457 /* find whether dependent l is installed or unpacked,
458 * and then find which package in the list satisfies it */
459 for(m = 0; m < all->len; m++) {
461 if ( dep->state_status != SS_NOT_INSTALLED)
462 if ( ! strcmp(dep->name, dependents[l]->name)) {
463 opkg_recurse_pkgs_in_order(conf, dep, all,
465 /* Stop the outer loop */
466 l = abpkg->provided_by->len;
467 /* break from the inner loop */
476 /* When all recursions from this node down, are over, and all
477 dependencies have been added in proper order in the ordered array, add
478 also the package pkg to ordered array */
479 pkg_vec_insert(ordered, pkg);
485 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
487 pkg_vec_t *all, *ordered, *visited;
493 opkg_message(conf, OPKG_INFO,
494 "Configuring unpacked packages\n");
497 all = pkg_vec_alloc();
499 pkg_hash_fetch_available(&conf->pkg_hash, all);
501 /* Reorder pkgs in order to be configured according to the Depends: tag
503 opkg_message(conf, OPKG_INFO,
504 "Reordering packages before configuring them...\n");
505 ordered = pkg_vec_alloc();
506 visited = pkg_vec_alloc();
507 for(i = 0; i < all->len; i++) {
509 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
513 ic = opkg_prep_intercepts (conf);
515 for(i = 0; i < all->len; i++) {
518 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
521 if (pkg->state_status == SS_UNPACKED) {
522 opkg_message(conf, OPKG_NOTICE,
523 "Configuring %s\n", pkg->name);
525 r = opkg_configure(conf, pkg);
527 pkg->state_status = SS_INSTALLED;
528 pkg->parent->state_status = SS_INSTALLED;
529 pkg->state_flag &= ~SF_PREFER;
537 r = opkg_finalize_intercepts (ic);
542 pkg_vec_free(ordered);
543 pkg_vec_free(visited);
548 static opkg_conf_t *global_conf;
550 static void sigint_handler(int sig)
552 signal(sig, SIG_DFL);
553 opkg_message(NULL, OPKG_NOTICE,
554 "opkg: interrupted. writing out status database\n");
555 write_status_files_if_changed(global_conf);
559 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
566 signal(SIGINT, sigint_handler);
569 * Now scan through package names and install
571 for (i=0; i < argc; i++) {
574 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
575 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
576 if (err != EINVAL && err != 0)
579 pkg_info_preinstall_check(conf);
581 for (i=0; i < argc; i++) {
583 err = opkg_install_by_name(conf, arg);
584 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
585 opkg_message(conf, OPKG_ERROR,
586 "Cannot find package %s.\n",
591 /* recheck to verify that all dependences are satisfied */
592 if (0) opkg_satisfy_all_dependences(conf);
594 opkg_configure_packages(conf, NULL);
596 write_status_files_if_changed(conf);
601 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
608 signal(SIGINT, sigint_handler);
611 for (i=0; i < argc; i++) {
614 err = opkg_prepare_url_for_install(conf, arg, &arg);
615 if (err != EINVAL && err != 0)
618 pkg_info_preinstall_check(conf);
620 for (i=0; i < argc; i++) {
622 if (conf->restrict_to_default_dest) {
623 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
627 opkg_message(conf, OPKG_NOTICE,
628 "Package %s not installed in %s\n",
629 argv[i], conf->default_dest->name);
633 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
637 opkg_upgrade_pkg(conf, pkg);
639 opkg_install_by_name(conf, arg);
643 pkg_vec_t *installed = pkg_vec_alloc();
645 pkg_info_preinstall_check(conf);
647 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
648 for (i = 0; i < installed->len; i++) {
649 pkg = installed->pkgs[i];
650 opkg_upgrade_pkg(conf, pkg);
652 pkg_vec_free(installed);
655 /* recheck to verify that all dependences are satisfied */
656 if (0) opkg_satisfy_all_dependences(conf);
658 opkg_configure_packages(conf, NULL);
660 write_status_files_if_changed(conf);
665 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
671 pkg_info_preinstall_check(conf);
672 for (i = 0; i < argc; i++) {
675 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
677 opkg_message(conf, OPKG_ERROR,
678 "Cannot find package %s.\n"
679 "Check the spelling or perhaps run 'opkg update'\n",
684 err = opkg_download_pkg(conf, pkg, ".");
687 opkg_message(conf, OPKG_ERROR,
688 "Failed to download %s\n", pkg->name);
690 opkg_message(conf, OPKG_NOTICE,
691 "Downloaded %s as %s\n",
692 pkg->name, pkg->local_filename);
700 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
703 pkg_vec_t *available;
705 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
707 char *pkg_name = NULL;
713 available = pkg_vec_alloc();
714 pkg_hash_fetch_available(&conf->pkg_hash, available);
715 pkg_vec_sort(available, pkg_compare_names);
716 for (i=0; i < available->len; i++) {
717 pkg = available->pkgs[i];
718 /* if we have package name or pattern and pkg does not match, then skip it */
719 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
721 if (pkg->description) {
722 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
724 desc_short[0] = '\0';
726 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
727 newline = strchr(desc_short, '\n');
732 version_str = pkg_version_str_alloc(pkg);
733 opkg_cb_list(pkg->name,desc_short,
740 pkg_vec_free(available);
746 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
749 pkg_vec_t *available;
751 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
753 char *pkg_name = NULL;
759 available = pkg_vec_alloc();
760 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
761 pkg_vec_sort(available, pkg_compare_names);
762 for (i=0; i < available->len; i++) {
763 pkg = available->pkgs[i];
764 /* if we have package name or pattern and pkg does not match, then skip it */
765 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
767 if (pkg->description) {
768 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
770 desc_short[0] = '\0';
772 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
773 newline = strchr(desc_short, '\n');
778 version_str = pkg_version_str_alloc(pkg);
779 opkg_cb_list(pkg->name,desc_short,
790 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
792 struct active_list *head = prepare_upgrade_list(conf);
793 struct active_list *node=NULL;
794 pkg_t *_old_pkg, *_new_pkg;
796 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
797 _old_pkg = list_entry(node, pkg_t, list);
798 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
799 old_v = pkg_version_str_alloc(_old_pkg);
800 new_v = pkg_version_str_alloc(_new_pkg);
802 opkg_cb_list(_old_pkg->name, new_v, old_v, _old_pkg->state_status, p_userdata);
806 active_list_head_delete(head);
810 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
813 pkg_vec_t *available;
815 char *pkg_name = NULL;
816 char **pkg_fields = NULL;
824 pkg_fields = &argv[1];
828 available = pkg_vec_alloc();
830 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
832 pkg_hash_fetch_available(&conf->pkg_hash, available);
833 for (i=0; i < available->len; i++) {
834 pkg = available->pkgs[i];
835 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
839 buff = pkg_formatted_info(pkg);
841 if (opkg_cb_status) opkg_cb_status(pkg->name,
846 We should not forget that actually the pointer is allocated.
847 We need to free it :) ( Thanks florian for seeing the error )
852 if (conf->verbosity > 1) {
853 conffile_list_elt_t *iter;
854 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
855 conffile_t *cf = (conffile_t *)iter->data;
856 int modified = conffile_has_been_modified(conf, cf);
857 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
858 cf->name, cf->value, modified);
862 pkg_vec_free(available);
867 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
869 return opkg_info_status_cmd(conf, argc, argv, 0);
872 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
874 return opkg_info_status_cmd(conf, argc, argv, 1);
877 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
882 char *pkg_name = NULL;
886 err = opkg_configure_packages (conf, pkg_name);
889 err = opkg_configure_packages (conf, NULL);
892 write_status_files_if_changed(conf);
897 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
903 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
904 err = glob(globpattern, 0, NULL, &globbuf);
910 opkg_message(conf, OPKG_NOTICE,
911 "The following packages in %s will now be installed.\n",
913 for (i = 0; i < globbuf.gl_pathc; i++) {
914 opkg_message(conf, OPKG_NOTICE,
915 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
917 opkg_message(conf, OPKG_NOTICE, "\n");
918 for (i = 0; i < globbuf.gl_pathc; i++) {
919 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
921 err = unlink(globbuf.gl_pathv[i]);
923 opkg_message(conf, OPKG_ERROR,
924 "%s: ERROR: failed to unlink %s: %s\n",
925 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
935 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
939 pkg_t *pkg_to_remove;
940 pkg_vec_t *available;
941 char *pkg_name = NULL;
943 signal(SIGINT, sigint_handler);
945 // ENH: Add the "no pkg removed" just in case.
949 pkg_info_preinstall_check(conf);
951 available = pkg_vec_alloc();
952 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
953 for (i=0; i < argc; i++) {
954 pkg_name = calloc(1, strlen(argv[i])+2);
955 strcpy(pkg_name,argv[i]);
956 for (a=0; a < available->len; a++) {
957 pkg = available->pkgs[a];
958 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
961 if (conf->restrict_to_default_dest) {
962 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
966 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
970 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
973 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
974 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
977 opkg_remove_pkg(conf, pkg_to_remove,0);
982 pkg_vec_free(available);
984 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
986 int flagged_pkg_count = 0;
989 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
991 for (i = 0; i < installed_pkgs->len; i++) {
992 pkg_t *pkg = installed_pkgs->pkgs[i];
993 if (pkg->state_flag & SF_USER) {
996 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
997 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
1000 if (!flagged_pkg_count) {
1001 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
1002 "so refusing to uninstall unflagged non-leaf packages\n");
1006 /* find packages not flagged SF_USER (i.e., installed to
1007 * satisfy a dependence) and not having any dependents, and
1011 for (i = 0; i < installed_pkgs->len; i++) {
1012 pkg_t *pkg = installed_pkgs->pkgs[i];
1013 if (!(pkg->state_flag & SF_USER)
1014 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1016 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1017 opkg_remove_pkg(conf, pkg,0);
1022 pkg_vec_free(installed_pkgs);
1026 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1028 write_status_files_if_changed(conf);
1032 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1038 signal(SIGINT, sigint_handler);
1040 pkg_info_preinstall_check(conf);
1042 for (i=0; i < argc; i++) {
1043 if (conf->restrict_to_default_dest) {
1044 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1046 conf->default_dest);
1048 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1052 opkg_message(conf, OPKG_ERROR,
1053 "Package %s is not installed.\n", argv[i]);
1056 opkg_purge_pkg(conf, pkg);
1059 write_status_files_if_changed(conf);
1063 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1067 const char *flags = argv[0];
1070 signal(SIGINT, sigint_handler);
1072 for (i=1; i < argc; i++) {
1073 if (conf->restrict_to_default_dest) {
1074 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1076 conf->default_dest);
1078 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1082 opkg_message(conf, OPKG_ERROR,
1083 "Package %s is not installed.\n", argv[i]);
1086 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1087 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1088 pkg->state_flag = pkg_state_flag_from_str(flags);
1090 /* pb_ asked this feature 03292004 */
1091 /* Actually I will use only this two, but this is an open for various status */
1092 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1093 pkg->state_status = pkg_state_status_from_str(flags);
1095 opkg_state_changed++;
1096 opkg_message(conf, OPKG_NOTICE,
1097 "Setting flags for package %s to %s\n",
1101 write_status_files_if_changed(conf);
1105 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1108 str_list_t *installed_files;
1109 str_list_elt_t *iter;
1111 size_t buff_len = 8192;
1115 buff = (char *)calloc(1, buff_len);
1116 if ( buff == NULL ) {
1117 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1125 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1128 opkg_message(conf, OPKG_ERROR,
1129 "Package %s not installed.\n", argv[0]);
1133 installed_files = pkg_get_installed_files(pkg);
1134 pkg_version = pkg_version_str_alloc(pkg);
1138 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1139 pkg->name, pkg_version, pkg->dest->name) + 1;
1140 if (used_len > buff_len) {
1142 buff = realloc (buff, buff_len);
1145 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1146 used_len += strlen (iter->data) + 1;
1147 while (buff_len <= used_len) {
1149 buff = realloc (buff, buff_len);
1151 strncat(buff, iter->data, buff_len);
1152 strncat(buff, "\n", buff_len);
1154 if (opkg_cb_list) opkg_cb_list(pkg->name,
1156 pkg_version_str_alloc(pkg),
1163 pkg_free_installed_files(pkg);
1168 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1172 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1173 const char *rel_str = "depends on";
1176 pkg_info_preinstall_check(conf);
1178 if (conf->query_all)
1179 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1181 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1182 for (i = 0; i < argc; i++) {
1183 const char *target = argv[i];
1186 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1188 for (j = 0; j < available_pkgs->len; j++) {
1189 pkg_t *pkg = available_pkgs->pkgs[j];
1190 if (fnmatch(target, pkg->name, 0) == 0) {
1192 int count = pkg->depends_count + pkg->pre_depends_count;
1193 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1194 target, pkg->architecture, rel_str);
1195 for (k = 0; k < count; k++) {
1196 compound_depend_t *cdepend = &pkg->depends[k];
1198 for (l = 0; l < cdepend->possibility_count; l++) {
1199 depend_t *possibility = cdepend->possibilities[l];
1200 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1201 if (conf->verbosity > 0) {
1202 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1203 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1204 if (possibility->version) {
1205 char *typestr = NULL;
1206 switch (possibility->constraint) {
1207 case NONE: typestr = "none"; break;
1208 case EARLIER: typestr = "<"; break;
1209 case EARLIER_EQUAL: typestr = "<="; break;
1210 case EQUAL: typestr = "="; break;
1211 case LATER_EQUAL: typestr = ">="; break;
1212 case LATER: typestr = ">"; break;
1214 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1218 opkg_message(conf, OPKG_ERROR, "\n");
1224 pkg_vec_free(available_pkgs);
1229 enum what_field_type {
1238 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1242 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1243 const char *rel_str = NULL;
1247 switch (what_field_type) {
1248 case WHATDEPENDS: rel_str = "depends on"; break;
1249 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1250 case WHATSUGGESTS: rel_str = "suggests"; break;
1251 case WHATRECOMMENDS: rel_str = "recommends"; break;
1252 case WHATPROVIDES: rel_str = "provides"; break;
1253 case WHATREPLACES: rel_str = "replaces"; break;
1256 if (conf->query_all)
1257 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1259 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1261 /* mark the root set */
1262 pkg_vec_clear_marks(available_pkgs);
1263 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1264 for (i = 0; i < argc; i++) {
1265 const char *dependee_pattern = argv[i];
1266 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1268 for (i = 0; i < available_pkgs->len; i++) {
1269 pkg_t *pkg = available_pkgs->pkgs[i];
1270 if (pkg->state_flag & SF_MARKED) {
1271 /* mark the parent (abstract) package */
1272 pkg_mark_provides(pkg);
1273 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1277 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1282 for (j = 0; j < available_pkgs->len; j++) {
1283 pkg_t *pkg = available_pkgs->pkgs[j];
1285 int count = ((what_field_type == WHATCONFLICTS)
1286 ? pkg->conflicts_count
1287 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1288 /* skip this package if it is already marked */
1289 if (pkg->parent->state_flag & SF_MARKED) {
1292 for (k = 0; k < count; k++) {
1293 compound_depend_t *cdepend =
1294 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1296 for (l = 0; l < cdepend->possibility_count; l++) {
1297 depend_t *possibility = cdepend->possibilities[l];
1298 if (possibility->pkg->state_flag & SF_MARKED) {
1299 /* mark the depending package so we won't visit it again */
1300 pkg->state_flag |= SF_MARKED;
1301 pkg_mark_provides(pkg);
1304 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1305 if (conf->verbosity > 0) {
1306 char *ver = pkg_version_str_alloc(pkg);
1307 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1308 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1309 if (possibility->version) {
1310 char *typestr = NULL;
1311 switch (possibility->constraint) {
1312 case NONE: typestr = "none"; break;
1313 case EARLIER: typestr = "<"; break;
1314 case EARLIER_EQUAL: typestr = "<="; break;
1315 case EQUAL: typestr = "="; break;
1316 case LATER_EQUAL: typestr = ">="; break;
1317 case LATER: typestr = ">"; break;
1319 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1322 if (!pkg_dependence_satisfiable(conf, possibility))
1323 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1325 opkg_message(conf, OPKG_NOTICE, "\n");
1333 } while (changed && recursive);
1334 pkg_vec_free(available_pkgs);
1340 static int pkg_mark_provides(pkg_t *pkg)
1342 int provides_count = pkg->provides_count;
1343 abstract_pkg_t **provides = pkg->provides;
1345 pkg->parent->state_flag |= SF_MARKED;
1346 for (i = 0; i < provides_count; i++) {
1347 provides[i]->state_flag |= SF_MARKED;
1352 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1354 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1356 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1358 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1361 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1363 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1366 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1368 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1371 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1373 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1376 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1380 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1381 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1384 pkg_info_preinstall_check(conf);
1386 if (conf->query_all)
1387 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1389 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1390 for (i = 0; i < argc; i++) {
1391 const char *target = argv[i];
1394 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1396 for (j = 0; j < available_pkgs->len; j++) {
1397 pkg_t *pkg = available_pkgs->pkgs[j];
1399 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1400 for (k = 0; k < count; k++) {
1401 abstract_pkg_t *apkg =
1402 ((what_field_type == WHATPROVIDES)
1404 : pkg->replaces[k]);
1405 if (fnmatch(target, apkg->name, 0) == 0) {
1406 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1407 if (strcmp(target, apkg->name) != 0)
1408 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1409 opkg_message(conf, OPKG_ERROR, "\n");
1414 pkg_vec_free(available_pkgs);
1419 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1421 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1424 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1426 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1429 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1433 pkg_vec_t *installed;
1435 str_list_t *installed_files;
1436 str_list_elt_t *iter;
1437 char *installed_file;
1443 installed = pkg_vec_alloc();
1444 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1445 pkg_vec_sort(installed, pkg_compare_names);
1447 for (i=0; i < installed->len; i++) {
1448 pkg = installed->pkgs[i];
1450 installed_files = pkg_get_installed_files(pkg);
1452 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1453 installed_file = (char *)iter->data;
1454 if (fnmatch(argv[0], installed_file, 0)==0) {
1455 if (opkg_cb_list) opkg_cb_list(pkg->name,
1457 pkg_version_str_alloc(pkg),
1458 pkg->state_status, p_userdata);
1462 pkg_free_installed_files(pkg);
1465 pkg_vec_free(installed);
1470 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1473 /* this is a bit gross */
1475 parseVersion(&p1, argv[0]);
1476 parseVersion(&p2, argv[2]);
1477 return pkg_version_satisfied(&p1, &p2, argv[1]);
1479 opkg_message(conf, OPKG_ERROR,
1480 "opkg compare_versions <v1> <op> <v2>\n"
1481 "<op> is one of <= >= << >> =\n");
1486 #ifndef HOST_CPU_STR
1487 #define HOST_CPU_STR__(X) #X
1488 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1489 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1492 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1494 nv_pair_list_elt_t *l;
1496 list_for_each_entry(l, &conf->arch_list.head, node) {
1497 nv_pair_t *nv = (nv_pair_t *)l->data;
1498 printf("arch %s %s\n", nv->name, nv->value);