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 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
147 p_userdata = userdata;
150 result = (cmd->fun)(conf, argc, argv);
159 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
165 pkg_src_list_elt_t *iter;
169 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
171 if (! file_is_dir(lists_dir)) {
172 if (file_exists(lists_dir)) {
173 opkg_message(conf, OPKG_ERROR,
174 "%s: ERROR: %s exists, but is not a directory\n",
175 __FUNCTION__, lists_dir);
179 err = file_mkdir_hier(lists_dir, 0755);
181 opkg_message(conf, OPKG_ERROR,
182 "%s: ERROR: failed to make directory %s: %s\n",
183 __FUNCTION__, lists_dir, strerror(errno));
192 tmp = strdup ("/tmp/opkg.XXXXXX");
194 if (mkdtemp (tmp) == NULL) {
200 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
201 char *url, *list_file_name;
203 src = (pkg_src_t *)iter->data;
205 if (src->extra_data) /* debian style? */
206 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
207 src->gzip ? "Packages.gz" : "Packages");
209 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
211 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
216 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
217 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
219 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
220 in = fopen (tmp_file_name, "r");
221 out = fopen (list_file_name, "w");
230 unlink (tmp_file_name);
234 err = opkg_download(conf, url, list_file_name, NULL, NULL);
238 opkg_message(conf, OPKG_NOTICE,
239 "Updated list of available packages in %s\n",
243 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
244 if (conf->check_signature) {
245 /* download detached signitures to verify the package lists */
246 /* get the url for the sig file */
247 if (src->extra_data) /* debian style? */
248 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
251 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
253 /* create temporary file for it */
256 /* Put the signature in the right place */
257 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
259 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
262 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
265 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
267 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
269 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
271 /* We shouldn't unlink the signature ! */
272 // unlink (tmp_file_name);
273 free (tmp_file_name);
279 free(list_file_name);
289 struct opkg_intercept
295 typedef struct opkg_intercept *opkg_intercept_t;
297 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
299 opkg_intercept_t ctx;
304 ctx = calloc (1, sizeof (*ctx));
305 oldpath = getenv ("PATH");
307 ctx->oldpath = strdup (oldpath);
313 sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
314 setenv ("PATH", newpath, 1);
319 sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
320 if (mkdir (ctx->statedir, 0770) < 0) {
321 if (errno == EEXIST) {
322 free (ctx->statedir);
326 perror (ctx->statedir);
329 setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
333 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
340 setenv ("PATH", ctx->oldpath, 1);
346 dir = opendir (ctx->statedir);
349 while (de = readdir (dir), de != NULL) {
352 if (de->d_name[0] == '.')
355 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
356 if (access (path, X_OK) == 0) {
366 perror (ctx->statedir);
368 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
372 free (ctx->statedir);
378 /* For package pkg do the following: If it is already visited, return. If not,
379 add it in visited list and recurse to its deps. Finally, add it to ordered
381 pkg_vec all contains all available packages in repos.
382 pkg_vec visited contains packages already visited by this function, and is
383 used to end recursion and avoid an infinite loop on graph cycles.
384 pkg_vec ordered will finally contain the ordered set of packages.
386 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
387 pkg_vec_t *visited, pkg_vec_t *ordered)
392 compound_depend_t * compound_depend;
393 depend_t ** possible_satisfiers;
394 abstract_pkg_t *abpkg;
395 abstract_pkg_t **dependents;
397 /* If it's just an available package, that is, not installed and not even
399 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
400 would do here. However, if there is an intermediate node (pkg) that is
401 configured and installed between two unpacked packages, the latter
402 won't be properly reordered, unless all installed/unpacked pkgs are
404 if (pkg->state_status == SS_NOT_INSTALLED)
407 /* If the package has already been visited (by this function), skip it */
408 for(j = 0; j < visited->len; j++)
409 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
410 opkg_message(conf, OPKG_INFO,
411 " pkg: %s already visited\n", pkg->name);
415 pkg_vec_insert(visited, pkg);
417 count = pkg->pre_depends_count + pkg->depends_count + \
418 pkg->recommends_count + pkg->suggests_count;
420 opkg_message(conf, OPKG_INFO,
421 " pkg: %s\n", pkg->name);
423 /* Iterate over all the dependencies of pkg. For each one, find a package
424 that is either installed or unpacked and satisfies this dependency.
425 (there should only be one such package per dependency installed or
426 unpacked). Then recurse to the dependency package */
427 for (j=0; j < count ; j++) {
428 compound_depend = &pkg->depends[j];
429 possible_satisfiers = compound_depend->possibilities;
430 for (k=0; k < compound_depend->possibility_count ; k++) {
431 abpkg = possible_satisfiers[k]->pkg;
432 dependents = abpkg->provided_by->pkgs;
434 if (dependents != NULL)
435 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
436 opkg_message(conf, OPKG_INFO,
437 " Descending on pkg: %s\n",
438 dependents [l]->name);
440 /* find whether dependent l is installed or unpacked,
441 * and then find which package in the list satisfies it */
442 for(m = 0; m < all->len; m++) {
444 if ( dep->state_status != SS_NOT_INSTALLED)
445 if ( ! strcmp(dep->name, dependents[l]->name)) {
446 opkg_recurse_pkgs_in_order(conf, dep, all,
448 /* Stop the outer loop */
449 l = abpkg->provided_by->len;
450 /* break from the inner loop */
459 /* When all recursions from this node down, are over, and all
460 dependencies have been added in proper order in the ordered array, add
461 also the package pkg to ordered array */
462 pkg_vec_insert(ordered, pkg);
468 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
470 pkg_vec_t *all, *ordered, *visited;
476 opkg_message(conf, OPKG_INFO,
477 "Configuring unpacked packages\n");
480 all = pkg_vec_alloc();
482 pkg_hash_fetch_available(&conf->pkg_hash, all);
484 /* Reorder pkgs in order to be configured according to the Depends: tag
486 opkg_message(conf, OPKG_INFO,
487 "Reordering packages before configuring them...\n");
488 ordered = pkg_vec_alloc();
489 visited = pkg_vec_alloc();
490 for(i = 0; i < all->len; i++) {
492 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
496 ic = opkg_prep_intercepts (conf);
498 for(i = 0; i < all->len; i++) {
501 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
504 if (pkg->state_status == SS_UNPACKED) {
505 opkg_message(conf, OPKG_NOTICE,
506 "Configuring %s\n", pkg->name);
508 r = opkg_configure(conf, pkg);
510 pkg->state_status = SS_INSTALLED;
511 pkg->parent->state_status = SS_INSTALLED;
512 pkg->state_flag &= ~SF_PREFER;
520 r = opkg_finalize_intercepts (ic);
525 pkg_vec_free(ordered);
526 pkg_vec_free(visited);
531 static opkg_conf_t *global_conf;
533 static void sigint_handler(int sig)
535 signal(sig, SIG_DFL);
536 opkg_message(NULL, OPKG_NOTICE,
537 "opkg: interrupted. writing out status database\n");
538 write_status_files_if_changed(global_conf);
542 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
549 signal(SIGINT, sigint_handler);
552 * Now scan through package names and install
554 for (i=0; i < argc; i++) {
557 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
558 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
559 if (err != EINVAL && err != 0)
562 pkg_info_preinstall_check(conf);
564 for (i=0; i < argc; i++) {
566 err = opkg_install_by_name(conf, arg);
567 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
568 opkg_message(conf, OPKG_ERROR,
569 "Cannot find package %s.\n",
574 /* recheck to verify that all dependences are satisfied */
575 if (0) opkg_satisfy_all_dependences(conf);
577 opkg_configure_packages(conf, NULL);
579 write_status_files_if_changed(conf);
584 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
591 signal(SIGINT, sigint_handler);
594 for (i=0; i < argc; i++) {
597 err = opkg_prepare_url_for_install(conf, arg, &arg);
598 if (err != EINVAL && err != 0)
601 pkg_info_preinstall_check(conf);
603 for (i=0; i < argc; i++) {
605 if (conf->restrict_to_default_dest) {
606 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
610 opkg_message(conf, OPKG_NOTICE,
611 "Package %s not installed in %s\n",
612 argv[i], conf->default_dest->name);
616 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
620 opkg_upgrade_pkg(conf, pkg);
622 opkg_install_by_name(conf, arg);
626 pkg_vec_t *installed = pkg_vec_alloc();
628 pkg_info_preinstall_check(conf);
630 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
631 for (i = 0; i < installed->len; i++) {
632 pkg = installed->pkgs[i];
633 opkg_upgrade_pkg(conf, pkg);
635 pkg_vec_free(installed);
638 /* recheck to verify that all dependences are satisfied */
639 if (0) opkg_satisfy_all_dependences(conf);
641 opkg_configure_packages(conf, NULL);
643 write_status_files_if_changed(conf);
648 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
654 pkg_info_preinstall_check(conf);
655 for (i = 0; i < argc; i++) {
658 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
660 opkg_message(conf, OPKG_ERROR,
661 "Cannot find package %s.\n"
662 "Check the spelling or perhaps run 'opkg update'\n",
667 err = opkg_download_pkg(conf, pkg, ".");
670 opkg_message(conf, OPKG_ERROR,
671 "Failed to download %s\n", pkg->name);
673 opkg_message(conf, OPKG_NOTICE,
674 "Downloaded %s as %s\n",
675 pkg->name, pkg->local_filename);
683 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
686 pkg_vec_t *available;
688 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
690 char *pkg_name = NULL;
696 available = pkg_vec_alloc();
697 pkg_hash_fetch_available(&conf->pkg_hash, available);
698 pkg_vec_sort(available, pkg_compare_names);
699 for (i=0; i < available->len; i++) {
700 pkg = available->pkgs[i];
701 /* if we have package name or pattern and pkg does not match, then skip it */
702 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
704 if (pkg->description) {
705 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
707 desc_short[0] = '\0';
709 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
710 newline = strchr(desc_short, '\n');
715 version_str = pkg_version_str_alloc(pkg);
716 opkg_cb_list(pkg->name,desc_short,
723 pkg_vec_free(available);
729 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
732 pkg_vec_t *available;
734 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
736 char *pkg_name = NULL;
742 available = pkg_vec_alloc();
743 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
744 pkg_vec_sort(available, pkg_compare_names);
745 for (i=0; i < available->len; i++) {
746 pkg = available->pkgs[i];
747 /* if we have package name or pattern and pkg does not match, then skip it */
748 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
750 if (pkg->description) {
751 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
753 desc_short[0] = '\0';
755 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
756 newline = strchr(desc_short, '\n');
761 version_str = pkg_version_str_alloc(pkg);
762 opkg_cb_list(pkg->name,desc_short,
770 pkg_vec_free(available);
775 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
777 struct active_list *head = prepare_upgrade_list(conf);
778 struct active_list *node=NULL;
779 pkg_t *_old_pkg, *_new_pkg;
781 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
782 _old_pkg = list_entry(node, pkg_t, list);
783 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
784 old_v = pkg_version_str_alloc(_old_pkg);
785 new_v = pkg_version_str_alloc(_new_pkg);
787 opkg_cb_list(_old_pkg->name, new_v, old_v, _old_pkg->state_status, p_userdata);
791 active_list_head_delete(head);
795 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
798 pkg_vec_t *available;
800 char *pkg_name = NULL;
801 char **pkg_fields = NULL;
809 pkg_fields = &argv[1];
813 available = pkg_vec_alloc();
815 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
817 pkg_hash_fetch_available(&conf->pkg_hash, available);
818 for (i=0; i < available->len; i++) {
819 pkg = available->pkgs[i];
820 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
824 buff = pkg_formatted_info(pkg);
826 if (opkg_cb_status) opkg_cb_status(pkg->name,
831 We should not forget that actually the pointer is allocated.
832 We need to free it :) ( Thanks florian for seeing the error )
837 if (conf->verbosity > 1) {
838 conffile_list_elt_t *iter;
839 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
840 conffile_t *cf = (conffile_t *)iter->data;
841 int modified = conffile_has_been_modified(conf, cf);
842 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
843 cf->name, cf->value, modified);
847 pkg_vec_free(available);
852 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
854 return opkg_info_status_cmd(conf, argc, argv, 0);
857 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
859 return opkg_info_status_cmd(conf, argc, argv, 1);
862 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
867 char *pkg_name = NULL;
871 err = opkg_configure_packages (conf, pkg_name);
874 err = opkg_configure_packages (conf, NULL);
877 write_status_files_if_changed(conf);
882 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
888 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
889 err = glob(globpattern, 0, NULL, &globbuf);
895 opkg_message(conf, OPKG_NOTICE,
896 "The following packages in %s will now be installed.\n",
898 for (i = 0; i < globbuf.gl_pathc; i++) {
899 opkg_message(conf, OPKG_NOTICE,
900 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
902 opkg_message(conf, OPKG_NOTICE, "\n");
903 for (i = 0; i < globbuf.gl_pathc; i++) {
904 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
906 err = unlink(globbuf.gl_pathv[i]);
908 opkg_message(conf, OPKG_ERROR,
909 "%s: ERROR: failed to unlink %s: %s\n",
910 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
920 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
924 pkg_t *pkg_to_remove;
925 pkg_vec_t *available;
926 char *pkg_name = NULL;
928 signal(SIGINT, sigint_handler);
930 // ENH: Add the "no pkg removed" just in case.
934 pkg_info_preinstall_check(conf);
936 available = pkg_vec_alloc();
937 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
938 for (i=0; i < argc; i++) {
939 pkg_name = calloc(1, strlen(argv[i])+2);
940 strcpy(pkg_name,argv[i]);
941 for (a=0; a < available->len; a++) {
942 pkg = available->pkgs[a];
943 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
946 if (conf->restrict_to_default_dest) {
947 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
951 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
954 if (pkg_to_remove == NULL) {
955 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
958 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
959 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
962 opkg_remove_pkg(conf, pkg_to_remove,0);
967 pkg_vec_free(available);
969 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
971 int flagged_pkg_count = 0;
974 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
976 for (i = 0; i < installed_pkgs->len; i++) {
977 pkg_t *pkg = installed_pkgs->pkgs[i];
978 if (pkg->state_flag & SF_USER) {
981 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
982 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
985 if (!flagged_pkg_count) {
986 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
987 "so refusing to uninstall unflagged non-leaf packages\n");
991 /* find packages not flagged SF_USER (i.e., installed to
992 * satisfy a dependence) and not having any dependents, and
996 for (i = 0; i < installed_pkgs->len; i++) {
997 pkg_t *pkg = installed_pkgs->pkgs[i];
998 if (!(pkg->state_flag & SF_USER)
999 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1001 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1002 opkg_remove_pkg(conf, pkg,0);
1007 pkg_vec_free(installed_pkgs);
1011 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1013 write_status_files_if_changed(conf);
1017 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1023 signal(SIGINT, sigint_handler);
1025 pkg_info_preinstall_check(conf);
1027 for (i=0; i < argc; i++) {
1028 if (conf->restrict_to_default_dest) {
1029 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1031 conf->default_dest);
1033 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1037 opkg_message(conf, OPKG_ERROR,
1038 "Package %s is not installed.\n", argv[i]);
1041 opkg_purge_pkg(conf, pkg);
1044 write_status_files_if_changed(conf);
1048 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1052 const char *flags = argv[0];
1055 signal(SIGINT, sigint_handler);
1057 for (i=1; i < argc; i++) {
1058 if (conf->restrict_to_default_dest) {
1059 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1061 conf->default_dest);
1063 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1067 opkg_message(conf, OPKG_ERROR,
1068 "Package %s is not installed.\n", argv[i]);
1071 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1072 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1073 pkg->state_flag = pkg_state_flag_from_str(flags);
1075 /* pb_ asked this feature 03292004 */
1076 /* Actually I will use only this two, but this is an open for various status */
1077 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1078 pkg->state_status = pkg_state_status_from_str(flags);
1080 opkg_state_changed++;
1081 opkg_message(conf, OPKG_NOTICE,
1082 "Setting flags for package %s to %s\n",
1086 write_status_files_if_changed(conf);
1090 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1093 str_list_t *installed_files;
1094 str_list_elt_t *iter;
1096 size_t buff_len = 8192;
1100 buff = (char *)calloc(1, buff_len);
1101 if ( buff == NULL ) {
1102 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1110 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1113 opkg_message(conf, OPKG_ERROR,
1114 "Package %s not installed.\n", argv[0]);
1118 installed_files = pkg_get_installed_files(pkg);
1119 pkg_version = pkg_version_str_alloc(pkg);
1123 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1124 pkg->name, pkg_version, pkg->dest->name) + 1;
1125 if (used_len > buff_len) {
1127 buff = realloc (buff, buff_len);
1130 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1131 used_len += strlen (iter->data) + 1;
1132 while (buff_len <= used_len) {
1134 buff = realloc (buff, buff_len);
1136 strncat(buff, iter->data, buff_len);
1137 strncat(buff, "\n", buff_len);
1139 if (opkg_cb_list) opkg_cb_list(pkg->name,
1141 pkg_version_str_alloc(pkg),
1148 pkg_free_installed_files(pkg);
1153 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1157 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1158 const char *rel_str = "depends on";
1161 pkg_info_preinstall_check(conf);
1163 if (conf->query_all)
1164 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1166 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1167 for (i = 0; i < argc; i++) {
1168 const char *target = argv[i];
1171 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1173 for (j = 0; j < available_pkgs->len; j++) {
1174 pkg_t *pkg = available_pkgs->pkgs[j];
1175 if (fnmatch(target, pkg->name, 0) == 0) {
1177 int count = pkg->depends_count + pkg->pre_depends_count;
1178 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1179 target, pkg->architecture, rel_str);
1180 for (k = 0; k < count; k++) {
1181 compound_depend_t *cdepend = &pkg->depends[k];
1183 for (l = 0; l < cdepend->possibility_count; l++) {
1184 depend_t *possibility = cdepend->possibilities[l];
1185 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1186 if (conf->verbosity > 0) {
1187 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1188 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1189 if (possibility->version) {
1190 char *typestr = NULL;
1191 switch (possibility->constraint) {
1192 case NONE: typestr = "none"; break;
1193 case EARLIER: typestr = "<"; break;
1194 case EARLIER_EQUAL: typestr = "<="; break;
1195 case EQUAL: typestr = "="; break;
1196 case LATER_EQUAL: typestr = ">="; break;
1197 case LATER: typestr = ">"; break;
1199 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1203 opkg_message(conf, OPKG_ERROR, "\n");
1209 pkg_vec_free(available_pkgs);
1214 enum what_field_type {
1223 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1227 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1228 const char *rel_str = NULL;
1232 switch (what_field_type) {
1233 case WHATDEPENDS: rel_str = "depends on"; break;
1234 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1235 case WHATSUGGESTS: rel_str = "suggests"; break;
1236 case WHATRECOMMENDS: rel_str = "recommends"; break;
1237 case WHATPROVIDES: rel_str = "provides"; break;
1238 case WHATREPLACES: rel_str = "replaces"; break;
1241 if (conf->query_all)
1242 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1244 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1246 /* mark the root set */
1247 pkg_vec_clear_marks(available_pkgs);
1248 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1249 for (i = 0; i < argc; i++) {
1250 const char *dependee_pattern = argv[i];
1251 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1253 for (i = 0; i < available_pkgs->len; i++) {
1254 pkg_t *pkg = available_pkgs->pkgs[i];
1255 if (pkg->state_flag & SF_MARKED) {
1256 /* mark the parent (abstract) package */
1257 pkg_mark_provides(pkg);
1258 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1262 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1267 for (j = 0; j < available_pkgs->len; j++) {
1268 pkg_t *pkg = available_pkgs->pkgs[j];
1270 int count = ((what_field_type == WHATCONFLICTS)
1271 ? pkg->conflicts_count
1272 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1273 /* skip this package if it is already marked */
1274 if (pkg->parent->state_flag & SF_MARKED) {
1277 for (k = 0; k < count; k++) {
1278 compound_depend_t *cdepend =
1279 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1281 for (l = 0; l < cdepend->possibility_count; l++) {
1282 depend_t *possibility = cdepend->possibilities[l];
1283 if (possibility->pkg->state_flag & SF_MARKED) {
1284 /* mark the depending package so we won't visit it again */
1285 pkg->state_flag |= SF_MARKED;
1286 pkg_mark_provides(pkg);
1289 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1290 if (conf->verbosity > 0) {
1291 char *ver = pkg_version_str_alloc(pkg);
1292 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1293 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1294 if (possibility->version) {
1295 char *typestr = NULL;
1296 switch (possibility->constraint) {
1297 case NONE: typestr = "none"; break;
1298 case EARLIER: typestr = "<"; break;
1299 case EARLIER_EQUAL: typestr = "<="; break;
1300 case EQUAL: typestr = "="; break;
1301 case LATER_EQUAL: typestr = ">="; break;
1302 case LATER: typestr = ">"; break;
1304 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1307 if (!pkg_dependence_satisfiable(conf, possibility))
1308 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1310 opkg_message(conf, OPKG_NOTICE, "\n");
1318 } while (changed && recursive);
1319 pkg_vec_free(available_pkgs);
1325 static int pkg_mark_provides(pkg_t *pkg)
1327 int provides_count = pkg->provides_count;
1328 abstract_pkg_t **provides = pkg->provides;
1330 pkg->parent->state_flag |= SF_MARKED;
1331 for (i = 0; i < provides_count; i++) {
1332 provides[i]->state_flag |= SF_MARKED;
1337 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1339 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1341 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1343 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1346 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1348 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1351 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1353 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1356 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1358 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1361 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1365 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1366 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1369 pkg_info_preinstall_check(conf);
1371 if (conf->query_all)
1372 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1374 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1375 for (i = 0; i < argc; i++) {
1376 const char *target = argv[i];
1379 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1381 for (j = 0; j < available_pkgs->len; j++) {
1382 pkg_t *pkg = available_pkgs->pkgs[j];
1384 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1385 for (k = 0; k < count; k++) {
1386 abstract_pkg_t *apkg =
1387 ((what_field_type == WHATPROVIDES)
1389 : pkg->replaces[k]);
1390 if (fnmatch(target, apkg->name, 0) == 0) {
1391 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1392 if (strcmp(target, apkg->name) != 0)
1393 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1394 opkg_message(conf, OPKG_ERROR, "\n");
1399 pkg_vec_free(available_pkgs);
1404 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1406 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1409 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1411 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1414 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1418 pkg_vec_t *installed;
1420 str_list_t *installed_files;
1421 str_list_elt_t *iter;
1422 char *installed_file;
1428 installed = pkg_vec_alloc();
1429 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1430 pkg_vec_sort(installed, pkg_compare_names);
1432 for (i=0; i < installed->len; i++) {
1433 pkg = installed->pkgs[i];
1435 installed_files = pkg_get_installed_files(pkg);
1437 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1438 installed_file = (char *)iter->data;
1439 if (fnmatch(argv[0], installed_file, 0)==0) {
1440 if (opkg_cb_list) opkg_cb_list(pkg->name,
1442 pkg_version_str_alloc(pkg),
1443 pkg->state_status, p_userdata);
1447 pkg_free_installed_files(pkg);
1450 pkg_vec_free(installed);
1455 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1458 /* this is a bit gross */
1460 parseVersion(&p1, argv[0]);
1461 parseVersion(&p2, argv[2]);
1462 return pkg_version_satisfied(&p1, &p2, argv[1]);
1464 opkg_message(conf, OPKG_ERROR,
1465 "opkg compare_versions <v1> <op> <v2>\n"
1466 "<op> is one of <= >= << >> =\n");
1471 #ifndef HOST_CPU_STR
1472 #define HOST_CPU_STR__(X) #X
1473 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1474 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1477 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1479 nv_pair_list_elt_t *l;
1481 list_for_each_entry(l, &conf->arch_list.head, node) {
1482 nv_pair_t *nv = (nv_pair_t *)l->data;
1483 printf("arch %s %s\n", nv->name, nv->value);