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 ocurred, 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 )
851 if (conf->verbosity > 1) {
852 conffile_list_elt_t *iter;
853 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
854 conffile_t *cf = (conffile_t *)iter->data;
855 int modified = conffile_has_been_modified(conf, cf);
856 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
857 cf->name, cf->value, modified);
861 pkg_vec_free(available);
866 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
868 return opkg_info_status_cmd(conf, argc, argv, 0);
871 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
873 return opkg_info_status_cmd(conf, argc, argv, 1);
876 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
881 char *pkg_name = NULL;
885 err = opkg_configure_packages (conf, pkg_name);
888 err = opkg_configure_packages (conf, NULL);
891 write_status_files_if_changed(conf);
896 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
902 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
903 err = glob(globpattern, 0, NULL, &globbuf);
909 opkg_message(conf, OPKG_NOTICE,
910 "The following packages in %s will now be installed.\n",
912 for (i = 0; i < globbuf.gl_pathc; i++) {
913 opkg_message(conf, OPKG_NOTICE,
914 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
916 opkg_message(conf, OPKG_NOTICE, "\n");
917 for (i = 0; i < globbuf.gl_pathc; i++) {
918 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
920 err = unlink(globbuf.gl_pathv[i]);
922 opkg_message(conf, OPKG_ERROR,
923 "%s: ERROR: failed to unlink %s: %s\n",
924 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
934 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
938 pkg_t *pkg_to_remove;
939 pkg_vec_t *available;
940 char *pkg_name = NULL;
942 signal(SIGINT, sigint_handler);
944 // ENH: Add the "no pkg removed" just in case.
948 pkg_info_preinstall_check(conf);
950 available = pkg_vec_alloc();
951 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
952 for (i=0; i < argc; i++) {
953 pkg_name = calloc(1, strlen(argv[i])+2);
954 strcpy(pkg_name,argv[i]);
955 for (a=0; a < available->len; a++) {
956 pkg = available->pkgs[a];
957 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
960 if (conf->restrict_to_default_dest) {
961 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
965 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
969 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
972 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
973 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
976 opkg_remove_pkg(conf, pkg_to_remove,0);
981 pkg_vec_free(available);
983 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
985 int flagged_pkg_count = 0;
988 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
990 for (i = 0; i < installed_pkgs->len; i++) {
991 pkg_t *pkg = installed_pkgs->pkgs[i];
992 if (pkg->state_flag & SF_USER) {
995 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
996 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
999 if (!flagged_pkg_count) {
1000 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
1001 "so refusing to uninstall unflagged non-leaf packages\n");
1005 /* find packages not flagged SF_USER (i.e., installed to
1006 * satisfy a dependence) and not having any dependents, and
1010 for (i = 0; i < installed_pkgs->len; i++) {
1011 pkg_t *pkg = installed_pkgs->pkgs[i];
1012 if (!(pkg->state_flag & SF_USER)
1013 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1015 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1016 opkg_remove_pkg(conf, pkg,0);
1021 pkg_vec_free(installed_pkgs);
1025 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1027 write_status_files_if_changed(conf);
1031 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1037 signal(SIGINT, sigint_handler);
1039 pkg_info_preinstall_check(conf);
1041 for (i=0; i < argc; i++) {
1042 if (conf->restrict_to_default_dest) {
1043 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1045 conf->default_dest);
1047 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1051 opkg_message(conf, OPKG_ERROR,
1052 "Package %s is not installed.\n", argv[i]);
1055 opkg_purge_pkg(conf, pkg);
1058 write_status_files_if_changed(conf);
1062 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1066 const char *flags = argv[0];
1069 signal(SIGINT, sigint_handler);
1071 for (i=1; i < argc; i++) {
1072 if (conf->restrict_to_default_dest) {
1073 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1075 conf->default_dest);
1077 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1081 opkg_message(conf, OPKG_ERROR,
1082 "Package %s is not installed.\n", argv[i]);
1085 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1086 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1087 pkg->state_flag = pkg_state_flag_from_str(flags);
1089 /* pb_ asked this feature 03292004 */
1090 /* Actually I will use only this two, but this is an open for various status */
1091 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1092 pkg->state_status = pkg_state_status_from_str(flags);
1094 opkg_state_changed++;
1095 opkg_message(conf, OPKG_NOTICE,
1096 "Setting flags for package %s to %s\n",
1100 write_status_files_if_changed(conf);
1104 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1107 str_list_t *installed_files;
1108 str_list_elt_t *iter;
1110 size_t buff_len = 8192;
1114 buff = (char *)calloc(1, buff_len);
1115 if ( buff == NULL ) {
1116 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1124 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1127 opkg_message(conf, OPKG_ERROR,
1128 "Package %s not installed.\n", argv[0]);
1132 installed_files = pkg_get_installed_files(pkg);
1133 pkg_version = pkg_version_str_alloc(pkg);
1137 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1138 pkg->name, pkg_version, pkg->dest->name) + 1;
1139 if (used_len > buff_len) {
1141 buff = realloc (buff, buff_len);
1144 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1145 used_len += strlen (iter->data) + 1;
1146 while (buff_len <= used_len) {
1148 buff = realloc (buff, buff_len);
1150 strncat(buff, iter->data, buff_len);
1151 strncat(buff, "\n", buff_len);
1153 if (opkg_cb_list) opkg_cb_list(pkg->name,
1155 pkg_version_str_alloc(pkg),
1162 pkg_free_installed_files(pkg);
1167 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1171 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1172 const char *rel_str = "depends on";
1175 pkg_info_preinstall_check(conf);
1177 if (conf->query_all)
1178 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1180 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1181 for (i = 0; i < argc; i++) {
1182 const char *target = argv[i];
1185 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1187 for (j = 0; j < available_pkgs->len; j++) {
1188 pkg_t *pkg = available_pkgs->pkgs[j];
1189 if (fnmatch(target, pkg->name, 0) == 0) {
1191 int count = pkg->depends_count + pkg->pre_depends_count;
1192 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1193 target, pkg->architecture, rel_str);
1194 for (k = 0; k < count; k++) {
1195 compound_depend_t *cdepend = &pkg->depends[k];
1197 for (l = 0; l < cdepend->possibility_count; l++) {
1198 depend_t *possibility = cdepend->possibilities[l];
1199 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1200 if (conf->verbosity > 0) {
1201 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1202 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1203 if (possibility->version) {
1204 char *typestr = NULL;
1205 switch (possibility->constraint) {
1206 case NONE: typestr = "none"; break;
1207 case EARLIER: typestr = "<"; break;
1208 case EARLIER_EQUAL: typestr = "<="; break;
1209 case EQUAL: typestr = "="; break;
1210 case LATER_EQUAL: typestr = ">="; break;
1211 case LATER: typestr = ">"; break;
1213 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1217 opkg_message(conf, OPKG_ERROR, "\n");
1223 pkg_vec_free(available_pkgs);
1228 enum what_field_type {
1237 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1241 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1242 const char *rel_str = NULL;
1246 switch (what_field_type) {
1247 case WHATDEPENDS: rel_str = "depends on"; break;
1248 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1249 case WHATSUGGESTS: rel_str = "suggests"; break;
1250 case WHATRECOMMENDS: rel_str = "recommends"; break;
1251 case WHATPROVIDES: rel_str = "provides"; break;
1252 case WHATREPLACES: rel_str = "replaces"; break;
1255 if (conf->query_all)
1256 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1258 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1260 /* mark the root set */
1261 pkg_vec_clear_marks(available_pkgs);
1262 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1263 for (i = 0; i < argc; i++) {
1264 const char *dependee_pattern = argv[i];
1265 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1267 for (i = 0; i < available_pkgs->len; i++) {
1268 pkg_t *pkg = available_pkgs->pkgs[i];
1269 if (pkg->state_flag & SF_MARKED) {
1270 /* mark the parent (abstract) package */
1271 pkg_mark_provides(pkg);
1272 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1276 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1281 for (j = 0; j < available_pkgs->len; j++) {
1282 pkg_t *pkg = available_pkgs->pkgs[j];
1284 int count = ((what_field_type == WHATCONFLICTS)
1285 ? pkg->conflicts_count
1286 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1287 /* skip this package if it is already marked */
1288 if (pkg->parent->state_flag & SF_MARKED) {
1291 for (k = 0; k < count; k++) {
1292 compound_depend_t *cdepend =
1293 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1295 for (l = 0; l < cdepend->possibility_count; l++) {
1296 depend_t *possibility = cdepend->possibilities[l];
1297 if (possibility->pkg->state_flag & SF_MARKED) {
1298 /* mark the depending package so we won't visit it again */
1299 pkg->state_flag |= SF_MARKED;
1300 pkg_mark_provides(pkg);
1303 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1304 if (conf->verbosity > 0) {
1305 char *ver = pkg_version_str_alloc(pkg);
1306 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1307 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1308 if (possibility->version) {
1309 char *typestr = NULL;
1310 switch (possibility->constraint) {
1311 case NONE: typestr = "none"; break;
1312 case EARLIER: typestr = "<"; break;
1313 case EARLIER_EQUAL: typestr = "<="; break;
1314 case EQUAL: typestr = "="; break;
1315 case LATER_EQUAL: typestr = ">="; break;
1316 case LATER: typestr = ">"; break;
1318 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1321 if (!pkg_dependence_satisfiable(conf, possibility))
1322 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1324 opkg_message(conf, OPKG_NOTICE, "\n");
1332 } while (changed && recursive);
1333 pkg_vec_free(available_pkgs);
1339 static int pkg_mark_provides(pkg_t *pkg)
1341 int provides_count = pkg->provides_count;
1342 abstract_pkg_t **provides = pkg->provides;
1344 pkg->parent->state_flag |= SF_MARKED;
1345 for (i = 0; i < provides_count; i++) {
1346 provides[i]->state_flag |= SF_MARKED;
1351 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1353 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1355 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1357 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1360 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1362 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1365 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1367 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1370 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1372 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1375 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1379 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1380 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1383 pkg_info_preinstall_check(conf);
1385 if (conf->query_all)
1386 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1388 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1389 for (i = 0; i < argc; i++) {
1390 const char *target = argv[i];
1393 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1395 for (j = 0; j < available_pkgs->len; j++) {
1396 pkg_t *pkg = available_pkgs->pkgs[j];
1398 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1399 for (k = 0; k < count; k++) {
1400 abstract_pkg_t *apkg =
1401 ((what_field_type == WHATPROVIDES)
1403 : pkg->replaces[k]);
1404 if (fnmatch(target, apkg->name, 0) == 0) {
1405 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1406 if (strcmp(target, apkg->name) != 0)
1407 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1408 opkg_message(conf, OPKG_ERROR, "\n");
1413 pkg_vec_free(available_pkgs);
1418 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1420 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1423 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1425 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1428 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1432 pkg_vec_t *installed;
1434 str_list_t *installed_files;
1435 str_list_elt_t *iter;
1436 char *installed_file;
1442 installed = pkg_vec_alloc();
1443 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1444 pkg_vec_sort(installed, pkg_compare_names);
1446 for (i=0; i < installed->len; i++) {
1447 pkg = installed->pkgs[i];
1449 installed_files = pkg_get_installed_files(pkg);
1451 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1452 installed_file = (char *)iter->data;
1453 if (fnmatch(argv[0], installed_file, 0)==0) {
1454 if (opkg_cb_list) opkg_cb_list(pkg->name,
1456 pkg_version_str_alloc(pkg),
1457 pkg->state_status, p_userdata);
1461 pkg_free_installed_files(pkg);
1464 pkg_vec_free(installed);
1469 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1472 /* this is a bit gross */
1474 parseVersion(&p1, argv[0]);
1475 parseVersion(&p2, argv[2]);
1476 return pkg_version_satisfied(&p1, &p2, argv[1]);
1478 opkg_message(conf, OPKG_ERROR,
1479 "opkg compare_versions <v1> <op> <v2>\n"
1480 "<op> is one of <= >= << >> =\n");
1485 #ifndef HOST_CPU_STR
1486 #define HOST_CPU_STR__(X) #X
1487 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1488 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1491 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1493 nv_pair_list_elt_t *l;
1495 list_for_each_entry(l, &conf->arch_list.head, node) {
1496 nv_pair_t *nv = (nv_pair_t *)l->data;
1497 printf("arch %s %s\n", nv->name, nv->value);