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.
24 #include "opkg_conf.h"
26 #include "opkg_message.h"
29 #include "pkg_parse.h"
30 #include "sprintf_alloc.h"
32 #include "file_util.h"
34 #include "libbb/libbb.h"
35 #include "opkg_utils.h"
36 #include "opkg_defines.h"
37 #include "opkg_download.h"
38 #include "opkg_install.h"
39 #include "opkg_upgrade.h"
40 #include "opkg_remove.h"
41 #include "opkg_configure.h"
42 #include "opkg_message.h"
46 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv);
47 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv);
48 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv);
49 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv);
50 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv);
51 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv);
52 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv);
53 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv);
54 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv);
55 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
56 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv);
57 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
58 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
70 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
71 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
72 static int pkg_mark_provides(pkg_t *pkg);
74 /* XXX: CLEANUP: The usage strings should be incorporated into this
75 array for easier maintenance */
76 static opkg_cmd_t cmds[] = {
77 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
78 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
79 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
80 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
81 {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
82 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
83 {"list-upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
84 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
85 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
86 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
87 {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd},
88 {"install-pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd},
89 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
90 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
91 {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
92 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
93 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
94 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
95 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
96 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
97 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
98 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
99 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
100 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
101 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
102 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
103 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
104 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
105 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
106 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
107 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
108 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
109 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
112 static void print_pkg(pkg_t *pkg)
114 char *version = pkg_version_str_alloc(pkg);
115 if (pkg->description)
116 printf("%s - %s - %s\n", pkg->name, version, pkg->description);
118 printf("%s - %s\n", pkg->name, version);
122 int opkg_state_changed;
123 static void write_status_files_if_changed(opkg_conf_t *conf)
125 if (opkg_state_changed && !conf->noaction) {
126 opkg_message(conf, OPKG_INFO,
127 " writing status file\n");
128 opkg_conf_write_status_files(conf);
129 pkg_write_changed_filelists(conf);
131 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
136 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
138 opkg_cmd_t *opkg_cmd_find(const char *name)
143 for (i=0; i < num_cmds; i++) {
145 if (strcmp(name, cmd->name) == 0) {
153 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
157 result = (cmd->fun)(conf, argc, argv);
165 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
171 pkg_src_list_elt_t *iter;
175 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
177 if (! file_is_dir(lists_dir)) {
178 if (file_exists(lists_dir)) {
179 opkg_message(conf, OPKG_ERROR,
180 "%s: ERROR: %s exists, but is not a directory\n",
181 __FUNCTION__, lists_dir);
185 err = file_mkdir_hier(lists_dir, 0755);
187 opkg_message(conf, OPKG_ERROR,
188 "%s: ERROR: failed to make directory %s: %s\n",
189 __FUNCTION__, lists_dir, strerror(errno));
197 sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
198 if (mkdtemp (tmp) == NULL) {
204 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
205 char *url, *list_file_name;
207 src = (pkg_src_t *)iter->data;
209 if (src->extra_data) /* debian style? */
210 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
211 src->gzip ? "Packages.gz" : "Packages");
213 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
215 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
220 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
221 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
223 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
224 in = fopen (tmp_file_name, "r");
225 out = fopen (list_file_name, "w");
234 unlink (tmp_file_name);
238 err = opkg_download(conf, url, list_file_name, NULL, NULL);
242 opkg_message(conf, OPKG_NOTICE,
243 "Updated list of available packages in %s\n",
247 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
248 if (conf->check_signature) {
249 /* download detached signitures to verify the package lists */
250 /* get the url for the sig file */
251 if (src->extra_data) /* debian style? */
252 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
255 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
257 /* create temporary file for it */
260 /* Put the signature in the right place */
261 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
263 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
266 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
269 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
271 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
273 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
275 /* We shouldn't unlink the signature ! */
276 // unlink (tmp_file_name);
277 free (tmp_file_name);
283 free(list_file_name);
293 struct opkg_intercept
299 typedef struct opkg_intercept *opkg_intercept_t;
301 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
303 opkg_intercept_t ctx;
306 ctx = xcalloc(1, sizeof (*ctx));
307 ctx->oldpath = xstrdup(getenv("PATH"));
308 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
309 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX", conf->tmp_dir);
311 if (mkdtemp(ctx->statedir) == NULL) {
312 fprintf(stderr, "%s: mkdtemp: %s\n", __FUNCTION__, strerror(errno));
320 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
321 setenv("PATH", newpath, 1);
327 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
332 setenv ("PATH", ctx->oldpath, 1);
335 dir = opendir (ctx->statedir);
338 while (de = readdir (dir), de != NULL) {
341 if (de->d_name[0] == '.')
344 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
345 if (access (path, X_OK) == 0) {
346 const char *argv[] = {"sh", "-c", path, NULL};
353 perror (ctx->statedir);
356 free (ctx->statedir);
362 /* For package pkg do the following: If it is already visited, return. If not,
363 add it in visited list and recurse to its deps. Finally, add it to ordered
365 pkg_vec all contains all available packages in repos.
366 pkg_vec visited contains packages already visited by this function, and is
367 used to end recursion and avoid an infinite loop on graph cycles.
368 pkg_vec ordered will finally contain the ordered set of packages.
370 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
371 pkg_vec_t *visited, pkg_vec_t *ordered)
376 compound_depend_t * compound_depend;
377 depend_t ** possible_satisfiers;
378 abstract_pkg_t *abpkg;
379 abstract_pkg_t **dependents;
381 /* If it's just an available package, that is, not installed and not even
383 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
384 would do here. However, if there is an intermediate node (pkg) that is
385 configured and installed between two unpacked packages, the latter
386 won't be properly reordered, unless all installed/unpacked pkgs are
388 if (pkg->state_status == SS_NOT_INSTALLED)
391 /* If the package has already been visited (by this function), skip it */
392 for(j = 0; j < visited->len; j++)
393 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
394 opkg_message(conf, OPKG_INFO,
395 " pkg: %s already visited\n", pkg->name);
399 pkg_vec_insert(visited, pkg);
401 count = pkg->pre_depends_count + pkg->depends_count + \
402 pkg->recommends_count + pkg->suggests_count;
404 opkg_message(conf, OPKG_INFO,
405 " pkg: %s\n", pkg->name);
407 /* Iterate over all the dependencies of pkg. For each one, find a package
408 that is either installed or unpacked and satisfies this dependency.
409 (there should only be one such package per dependency installed or
410 unpacked). Then recurse to the dependency package */
411 for (j=0; j < count ; j++) {
412 compound_depend = &pkg->depends[j];
413 possible_satisfiers = compound_depend->possibilities;
414 for (k=0; k < compound_depend->possibility_count ; k++) {
415 abpkg = possible_satisfiers[k]->pkg;
416 dependents = abpkg->provided_by->pkgs;
418 if (dependents != NULL)
419 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
420 opkg_message(conf, OPKG_INFO,
421 " Descending on pkg: %s\n",
422 dependents [l]->name);
424 /* find whether dependent l is installed or unpacked,
425 * and then find which package in the list satisfies it */
426 for(m = 0; m < all->len; m++) {
428 if ( dep->state_status != SS_NOT_INSTALLED)
429 if ( ! strcmp(dep->name, dependents[l]->name)) {
430 opkg_recurse_pkgs_in_order(conf, dep, all,
432 /* Stop the outer loop */
433 l = abpkg->provided_by->len;
434 /* break from the inner loop */
443 /* When all recursions from this node down, are over, and all
444 dependencies have been added in proper order in the ordered array, add
445 also the package pkg to ordered array */
446 pkg_vec_insert(ordered, pkg);
452 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
454 pkg_vec_t *all, *ordered, *visited;
460 opkg_message(conf, OPKG_INFO,
461 "Configuring unpacked packages\n");
464 all = pkg_vec_alloc();
466 pkg_hash_fetch_available(&conf->pkg_hash, all);
468 /* Reorder pkgs in order to be configured according to the Depends: tag
470 opkg_message(conf, OPKG_INFO,
471 "Reordering packages before configuring them...\n");
472 ordered = pkg_vec_alloc();
473 visited = pkg_vec_alloc();
474 for(i = 0; i < all->len; i++) {
476 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
479 ic = opkg_prep_intercepts (conf);
485 for(i = 0; i < all->len; i++) {
488 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
491 if (pkg->state_status == SS_UNPACKED) {
492 opkg_message(conf, OPKG_NOTICE,
493 "Configuring %s\n", pkg->name);
495 r = opkg_configure(conf, pkg);
497 pkg->state_status = SS_INSTALLED;
498 pkg->parent->state_status = SS_INSTALLED;
499 pkg->state_flag &= ~SF_PREFER;
507 r = opkg_finalize_intercepts (ic);
513 pkg_vec_free(ordered);
514 pkg_vec_free(visited);
519 static opkg_conf_t *global_conf;
521 static void sigint_handler(int sig)
523 signal(sig, SIG_DFL);
524 opkg_message(NULL, OPKG_NOTICE,
525 "opkg: interrupted. writing out status database\n");
526 write_status_files_if_changed(global_conf);
530 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
537 signal(SIGINT, sigint_handler);
540 * Now scan through package names and install
542 for (i=0; i < argc; i++) {
545 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
546 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
547 if (err != EINVAL && err != 0)
550 pkg_info_preinstall_check(conf);
552 for (i=0; i < argc; i++) {
554 err = opkg_install_by_name(conf, arg);
555 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
556 opkg_message(conf, OPKG_ERROR,
557 "Cannot find package %s.\n",
562 opkg_configure_packages(conf, NULL);
564 write_status_files_if_changed(conf);
569 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
576 signal(SIGINT, sigint_handler);
579 for (i=0; i < argc; i++) {
582 err = opkg_prepare_url_for_install(conf, arg, &arg);
583 if (err != EINVAL && err != 0)
586 pkg_info_preinstall_check(conf);
588 for (i=0; i < argc; i++) {
590 if (conf->restrict_to_default_dest) {
591 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
595 opkg_message(conf, OPKG_NOTICE,
596 "Package %s not installed in %s\n",
597 argv[i], conf->default_dest->name);
601 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
605 opkg_upgrade_pkg(conf, pkg);
607 opkg_install_by_name(conf, arg);
611 pkg_vec_t *installed = pkg_vec_alloc();
613 pkg_info_preinstall_check(conf);
615 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
616 for (i = 0; i < installed->len; i++) {
617 pkg = installed->pkgs[i];
618 opkg_upgrade_pkg(conf, pkg);
620 pkg_vec_free(installed);
623 opkg_configure_packages(conf, NULL);
625 write_status_files_if_changed(conf);
630 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
636 pkg_info_preinstall_check(conf);
637 for (i = 0; i < argc; i++) {
640 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
642 opkg_message(conf, OPKG_ERROR,
643 "Cannot find package %s.\n"
644 "Check the spelling or perhaps run 'opkg update'\n",
649 err = opkg_download_pkg(conf, pkg, ".");
652 opkg_message(conf, OPKG_ERROR,
653 "Failed to download %s\n", pkg->name);
655 opkg_message(conf, OPKG_NOTICE,
656 "Downloaded %s as %s\n",
657 pkg->name, pkg->local_filename);
665 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
668 pkg_vec_t *available;
670 char *pkg_name = NULL;
675 available = pkg_vec_alloc();
676 pkg_hash_fetch_available(&conf->pkg_hash, available);
677 pkg_vec_sort(available, pkg_compare_names);
678 for (i=0; i < available->len; i++) {
679 pkg = available->pkgs[i];
680 /* if we have package name or pattern and pkg does not match, then skip it */
681 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
685 pkg_vec_free(available);
691 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
694 pkg_vec_t *available;
696 char *pkg_name = NULL;
701 available = pkg_vec_alloc();
702 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
703 pkg_vec_sort(available, pkg_compare_names);
704 for (i=0; i < available->len; i++) {
705 pkg = available->pkgs[i];
706 /* if we have package name or pattern and pkg does not match, then skip it */
707 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
712 pkg_vec_free(available);
717 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
719 struct active_list *head = prepare_upgrade_list(conf);
720 struct active_list *node=NULL;
721 pkg_t *_old_pkg, *_new_pkg;
723 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
724 _old_pkg = list_entry(node, pkg_t, list);
725 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
726 old_v = pkg_version_str_alloc(_old_pkg);
727 new_v = pkg_version_str_alloc(_new_pkg);
728 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
732 active_list_head_delete(head);
736 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
739 pkg_vec_t *available;
741 char *pkg_name = NULL;
747 available = pkg_vec_alloc();
749 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
751 pkg_hash_fetch_available(&conf->pkg_hash, available);
753 for (i=0; i < available->len; i++) {
754 pkg = available->pkgs[i];
755 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
759 pkg_formatted_info(stdout, pkg);
761 if (conf->verbosity >= OPKG_NOTICE) {
762 conffile_list_elt_t *iter;
763 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
764 conffile_t *cf = (conffile_t *)iter->data;
765 int modified = conffile_has_been_modified(conf, cf);
767 opkg_message(conf, OPKG_NOTICE,
768 "conffile=%s md5sum=%s modified=%d\n",
769 cf->name, cf->value, modified);
773 pkg_vec_free(available);
778 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
780 return opkg_info_status_cmd(conf, argc, argv, 0);
783 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
785 return opkg_info_status_cmd(conf, argc, argv, 1);
788 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
793 char *pkg_name = NULL;
797 err = opkg_configure_packages (conf, pkg_name);
800 err = opkg_configure_packages (conf, NULL);
803 write_status_files_if_changed(conf);
808 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
814 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
815 err = glob(globpattern, 0, NULL, &globbuf);
821 opkg_message(conf, OPKG_NOTICE,
822 "The following packages in %s will now be installed.\n",
824 for (i = 0; i < globbuf.gl_pathc; i++) {
825 opkg_message(conf, OPKG_NOTICE,
826 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
828 opkg_message(conf, OPKG_NOTICE, "\n");
829 for (i = 0; i < globbuf.gl_pathc; i++) {
830 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
832 err = unlink(globbuf.gl_pathv[i]);
834 opkg_message(conf, OPKG_ERROR,
835 "%s: ERROR: failed to unlink %s: %s\n",
836 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
846 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
850 pkg_t *pkg_to_remove;
851 pkg_vec_t *available;
856 signal(SIGINT, sigint_handler);
858 pkg_info_preinstall_check(conf);
860 available = pkg_vec_alloc();
861 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
863 for (i=0; i<argc; i++) {
864 for (a=0; a<available->len; a++) {
865 pkg = available->pkgs[a];
866 if (fnmatch(argv[i], pkg->name, 0)) {
869 if (conf->restrict_to_default_dest) {
870 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
874 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
877 if (pkg_to_remove == NULL) {
878 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
881 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
882 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
885 opkg_remove_pkg(conf, pkg_to_remove, 0);
890 pkg_vec_free(available);
893 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
895 write_status_files_if_changed(conf);
899 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
905 signal(SIGINT, sigint_handler);
907 pkg_info_preinstall_check(conf);
909 for (i=0; i < argc; i++) {
910 if (conf->restrict_to_default_dest) {
911 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
915 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
919 opkg_message(conf, OPKG_ERROR,
920 "Package %s is not installed.\n", argv[i]);
923 opkg_purge_pkg(conf, pkg);
926 write_status_files_if_changed(conf);
930 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
934 const char *flags = argv[0];
937 signal(SIGINT, sigint_handler);
939 for (i=1; i < argc; i++) {
940 if (conf->restrict_to_default_dest) {
941 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
945 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
949 opkg_message(conf, OPKG_ERROR,
950 "Package %s is not installed.\n", argv[i]);
953 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
954 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
955 pkg->state_flag = pkg_state_flag_from_str(flags);
957 /* pb_ asked this feature 03292004 */
958 /* Actually I will use only this two, but this is an open for various status */
959 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
960 pkg->state_status = pkg_state_status_from_str(flags);
962 opkg_state_changed++;
963 opkg_message(conf, OPKG_NOTICE,
964 "Setting flags for package %s to %s\n",
968 write_status_files_if_changed(conf);
972 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
976 str_list_elt_t *iter;
983 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
986 opkg_message(conf, OPKG_ERROR,
987 "Package %s not installed.\n", argv[0]);
991 files = pkg_get_installed_files(conf, pkg);
992 pkg_version = pkg_version_str_alloc(pkg);
994 printf("Package %s (%s) is installed on %s and has the following files:\n",
995 pkg->name, pkg_version, pkg->dest->name);
997 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
998 printf("%s\n", (char *)iter->data);
1001 pkg_free_installed_files(pkg);
1006 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1010 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1011 const char *rel_str = "depends on";
1014 pkg_info_preinstall_check(conf);
1016 if (conf->query_all)
1017 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1019 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1020 for (i = 0; i < argc; i++) {
1021 const char *target = argv[i];
1024 opkg_message(conf, OPKG_NOTICE, "target=%s\n", target);
1026 for (j = 0; j < available_pkgs->len; j++) {
1027 pkg_t *pkg = available_pkgs->pkgs[j];
1028 if (fnmatch(target, pkg->name, 0) == 0) {
1030 int count = pkg->depends_count + pkg->pre_depends_count;
1031 opkg_message(conf, OPKG_NOTICE, "What %s (arch=%s) %s\n",
1032 target, pkg->architecture, rel_str);
1033 for (k = 0; k < count; k++) {
1034 compound_depend_t *cdepend = &pkg->depends[k];
1036 for (l = 0; l < cdepend->possibility_count; l++) {
1037 depend_t *possibility = cdepend->possibilities[l];
1038 opkg_message(conf, OPKG_NOTICE, " %s", possibility->pkg->name);
1039 if (conf->verbosity >= OPKG_NOTICE) {
1040 if (possibility->version) {
1041 char *typestr = NULL;
1042 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1043 switch (possibility->constraint) {
1044 case NONE: typestr = "none"; break;
1045 case EARLIER: typestr = "<"; break;
1046 case EARLIER_EQUAL: typestr = "<="; break;
1047 case EQUAL: typestr = "="; break;
1048 case LATER_EQUAL: typestr = ">="; break;
1049 case LATER: typestr = ">"; break;
1051 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1054 opkg_message(conf, OPKG_NOTICE, "\n");
1060 pkg_vec_free(available_pkgs);
1065 enum what_field_type {
1074 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum depend_type what_field_type, int recursive, int argc, char **argv)
1078 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1079 const char *rel_str = NULL;
1083 switch (what_field_type) {
1084 case DEPEND: rel_str = "depends on"; break;
1085 case CONFLICTS: rel_str = "conflicts with"; break;
1086 case SUGGEST: rel_str = "suggests"; break;
1087 case RECOMMEND: rel_str = "recommends"; break;
1091 if (conf->query_all)
1092 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1094 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1096 /* mark the root set */
1097 pkg_vec_clear_marks(available_pkgs);
1098 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1099 for (i = 0; i < argc; i++) {
1100 const char *dependee_pattern = argv[i];
1101 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1103 for (i = 0; i < available_pkgs->len; i++) {
1104 pkg_t *pkg = available_pkgs->pkgs[i];
1105 if (pkg->state_flag & SF_MARKED) {
1106 /* mark the parent (abstract) package */
1107 pkg_mark_provides(pkg);
1108 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1112 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1117 for (j = 0; j < available_pkgs->len; j++) {
1118 pkg_t *pkg = available_pkgs->pkgs[j];
1120 int count = ((what_field_type == CONFLICTS)
1121 ? pkg->conflicts_count
1122 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1123 /* skip this package if it is already marked */
1124 if (pkg->parent->state_flag & SF_MARKED) {
1127 for (k = 0; k < count; k++) {
1128 compound_depend_t *cdepend =
1129 (what_field_type == CONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1131 if (what_field_type != cdepend->type)
1133 for (l = 0; l < cdepend->possibility_count; l++) {
1134 depend_t *possibility = cdepend->possibilities[l];
1135 if (possibility->pkg->state_flag & SF_MARKED) {
1136 /* mark the depending package so we won't visit it again */
1137 pkg->state_flag |= SF_MARKED;
1138 pkg_mark_provides(pkg);
1141 if (conf->verbosity >= OPKG_NOTICE) {
1142 char *ver = pkg_version_str_alloc(pkg);
1143 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1144 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1145 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1146 if (possibility->version) {
1147 char *typestr = NULL;
1148 switch (possibility->constraint) {
1149 case NONE: typestr = "none"; break;
1150 case EARLIER: typestr = "<"; break;
1151 case EARLIER_EQUAL: typestr = "<="; break;
1152 case EQUAL: typestr = "="; break;
1153 case LATER_EQUAL: typestr = ">="; break;
1154 case LATER: typestr = ">"; break;
1156 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1159 if (!pkg_dependence_satisfiable(conf, possibility))
1160 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1162 opkg_message(conf, OPKG_NOTICE, "\n");
1170 } while (changed && recursive);
1171 pkg_vec_free(available_pkgs);
1177 static int pkg_mark_provides(pkg_t *pkg)
1179 int provides_count = pkg->provides_count;
1180 abstract_pkg_t **provides = pkg->provides;
1182 pkg->parent->state_flag |= SF_MARKED;
1183 for (i = 0; i < provides_count; i++) {
1184 provides[i]->state_flag |= SF_MARKED;
1189 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1191 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 1, argc, argv);
1193 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1195 return opkg_what_depends_conflicts_cmd(conf, DEPEND, 0, argc, argv);
1198 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1200 return opkg_what_depends_conflicts_cmd(conf, SUGGEST, 0, argc, argv);
1203 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1205 return opkg_what_depends_conflicts_cmd(conf, RECOMMEND, 0, argc, argv);
1208 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1210 return opkg_what_depends_conflicts_cmd(conf, CONFLICTS, 0, argc, argv);
1213 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1217 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1218 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1221 pkg_info_preinstall_check(conf);
1223 if (conf->query_all)
1224 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1226 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1227 for (i = 0; i < argc; i++) {
1228 const char *target = argv[i];
1231 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1233 for (j = 0; j < available_pkgs->len; j++) {
1234 pkg_t *pkg = available_pkgs->pkgs[j];
1236 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1237 for (k = 0; k < count; k++) {
1238 abstract_pkg_t *apkg =
1239 ((what_field_type == WHATPROVIDES)
1241 : pkg->replaces[k]);
1242 if (fnmatch(target, apkg->name, 0) == 0) {
1243 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1244 if (strcmp(target, apkg->name) != 0)
1245 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1246 opkg_message(conf, OPKG_ERROR, "\n");
1251 pkg_vec_free(available_pkgs);
1256 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1258 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1261 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1263 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1266 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1270 pkg_vec_t *installed;
1272 str_list_t *installed_files;
1273 str_list_elt_t *iter;
1274 char *installed_file;
1280 installed = pkg_vec_alloc();
1281 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1282 pkg_vec_sort(installed, pkg_compare_names);
1284 for (i=0; i < installed->len; i++) {
1285 pkg = installed->pkgs[i];
1287 installed_files = pkg_get_installed_files(conf, pkg);
1289 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1290 installed_file = (char *)iter->data;
1291 if (fnmatch(argv[0], installed_file, 0)==0)
1295 pkg_free_installed_files(pkg);
1298 pkg_vec_free(installed);
1303 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1306 /* this is a bit gross */
1308 parse_version(&p1, argv[0]);
1309 parse_version(&p2, argv[2]);
1310 return pkg_version_satisfied(&p1, &p2, argv[1]);
1312 opkg_message(conf, OPKG_ERROR,
1313 "opkg compare_versions <v1> <op> <v2>\n"
1314 "<op> is one of <= >= << >> =\n");
1319 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1321 nv_pair_list_elt_t *l;
1323 list_for_each_entry(l, &conf->arch_list.head, node) {
1324 nv_pair_t *nv = (nv_pair_t *)l->data;
1325 printf("arch %s %s\n", nv->name, nv->value);