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_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
70 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
71 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
72 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
73 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
74 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
75 static int pkg_mark_provides(pkg_t *pkg);
77 /* XXX: CLEANUP: The usage strings should be incorporated into this
78 array for easier maintenance */
79 static opkg_cmd_t cmds[] = {
80 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
81 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
82 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
83 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_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", 1, (opkg_cmd_fun_t)opkg_install_cmd},
89 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
90 {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
91 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
92 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
93 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
94 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
95 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
96 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
97 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
98 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
99 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
100 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
101 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
102 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
103 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
104 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
105 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
106 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
107 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
108 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
111 int opkg_state_changed;
112 static void write_status_files_if_changed(opkg_conf_t *conf)
114 if (opkg_state_changed && !conf->noaction) {
115 opkg_message(conf, OPKG_INFO,
116 " writing status file\n");
117 opkg_conf_write_status_files(conf);
118 pkg_write_changed_filelists(conf);
120 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
125 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
127 opkg_cmd_t *opkg_cmd_find(const char *name)
132 for (i=0; i < num_cmds; i++) {
134 if (strcmp(name, cmd->name) == 0) {
142 void opkg_print_error_list (opkg_conf_t *conf)
145 reverse_error_list(&error_list);
147 printf ("Collected errors:\n");
148 /* Here we print the errors collected and free the list */
149 while (error_list != NULL) {
150 printf (" * %s", error_list->errmsg);
151 error_list = error_list->next;
154 free_error_list(&error_list);
159 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
162 p_userdata = userdata;
165 result = (cmd->fun)(conf, argc, argv);
167 if ( result != 0 && !error_list) {
168 opkg_message(conf, OPKG_NOTICE, "An error ocurred, return value: %d.\n", result);
171 opkg_print_error_list (conf);
177 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
183 pkg_src_list_elt_t *iter;
187 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
189 if (! file_is_dir(lists_dir)) {
190 if (file_exists(lists_dir)) {
191 opkg_message(conf, OPKG_ERROR,
192 "%s: ERROR: %s exists, but is not a directory\n",
193 __FUNCTION__, lists_dir);
197 err = file_mkdir_hier(lists_dir, 0755);
199 opkg_message(conf, OPKG_ERROR,
200 "%s: ERROR: failed to make directory %s: %s\n",
201 __FUNCTION__, lists_dir, strerror(errno));
210 tmp = strdup ("/tmp/opkg.XXXXXX");
212 if (mkdtemp (tmp) == NULL) {
218 for (iter = conf->pkg_src_list.head; iter; iter = iter->next) {
219 char *url, *list_file_name;
223 if (src->extra_data) /* debian style? */
224 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
225 src->gzip ? "Packages.gz" : "Packages");
227 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
229 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
234 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
235 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
237 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
238 in = fopen (tmp_file_name, "r");
239 out = fopen (list_file_name, "w");
248 unlink (tmp_file_name);
251 err = opkg_download(conf, url, list_file_name, NULL, NULL);
255 opkg_message(conf, OPKG_NOTICE,
256 "Updated list of available packages in %s\n",
262 /* download detached signitures to verify the package lists */
263 /* get the url for the sig file */
264 if (src->extra_data) /* debian style? */
265 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
268 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
270 /* create temporary file for it */
273 sprintf_alloc (&tmp_file_name, "%s/%s", tmp, "Packages.sig");
275 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
278 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
281 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
283 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
285 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
287 unlink (tmp_file_name);
288 free (tmp_file_name);
291 opkg_message (conf, OPKG_NOTICE, "Signiture check for %s skipped "
292 "because GPG support was not enabled in this build\n", src->name);
294 free(list_file_name);
304 struct opkg_intercept
310 typedef struct opkg_intercept *opkg_intercept_t;
312 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
314 opkg_intercept_t ctx;
318 ctx = malloc (sizeof (*ctx));
319 ctx->oldpath = strdup (getenv ("PATH"));
321 sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
322 setenv ("PATH", newpath, 1);
327 sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
328 if (mkdir (ctx->statedir, 0770) < 0) {
329 if (errno == EEXIST) {
330 free (ctx->statedir);
334 perror (ctx->statedir);
337 setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
341 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
347 setenv ("PATH", ctx->oldpath, 1);
350 dir = opendir (ctx->statedir);
353 while (de = readdir (dir), de != NULL) {
356 if (de->d_name[0] == '.')
359 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
360 if (access (path, X_OK) == 0) {
369 perror (ctx->statedir);
371 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
375 free (ctx->statedir);
381 /* For package pkg do the following: If it is already visited, return. If not,
382 add it in visited list and recurse to its deps. Finally, add it to ordered
384 pkg_vec all contains all available packages in repos.
385 pkg_vec visited contains packages already visited by this function, and is
386 used to end recursion and avoid an infinite loop on graph cycles.
387 pkg_vec ordered will finally contain the ordered set of packages.
389 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
390 pkg_vec_t *visited, pkg_vec_t *ordered)
395 compound_depend_t * compound_depend;
396 depend_t ** possible_satisfiers;
397 abstract_pkg_t *abpkg;
398 abstract_pkg_t **dependents;
400 /* If it's just an available package, that is, not installed and not even
402 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
403 would do here. However, if there is an intermediate node (pkg) that is
404 configured and installed between two unpacked packages, the latter
405 won't be properly reordered, unless all installed/unpacked pkgs are
407 if (pkg->state_status == SS_NOT_INSTALLED)
410 /* If the package has already been visited (by this function), skip it */
411 for(j = 0; j < visited->len; j++)
412 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
413 opkg_message(conf, OPKG_INFO,
414 " pkg: %s already visited\n", pkg->name);
418 pkg_vec_insert(visited, pkg);
420 count = pkg->pre_depends_count + pkg->depends_count + \
421 pkg->recommends_count + pkg->suggests_count;
423 opkg_message(conf, OPKG_INFO,
424 " pkg: %s\n", pkg->name);
426 /* Iterate over all the dependencies of pkg. For each one, find a package
427 that is either installed or unpacked and satisfies this dependency.
428 (there should only be one such package per dependency installed or
429 unpacked). Then recurse to the dependency package */
430 for (j=0; j < count ; j++) {
431 compound_depend = &pkg->depends[j];
432 possible_satisfiers = compound_depend->possibilities;
433 for (k=0; k < compound_depend->possibility_count ; k++) {
434 abpkg = possible_satisfiers[k]->pkg;
435 dependents = abpkg->provided_by->pkgs;
437 if (dependents != NULL)
438 while (dependents [l] != NULL && l < abpkg->provided_by->len) {
439 opkg_message(conf, OPKG_INFO,
440 " Descending on pkg: %s\n",
441 dependents [l]->name);
443 /* find whether dependent l is installed or unpacked,
444 * and then find which package in the list satisfies it */
445 for(m = 0; m < all->len; m++) {
447 if ( dep->state_status != SS_NOT_INSTALLED)
448 if ( ! strcmp(dep->name, dependents[l]->name)) {
449 opkg_recurse_pkgs_in_order(conf, dep, all,
451 /* Stop the outer loop */
452 l = abpkg->provided_by->len;
453 /* break from the inner loop */
462 /* When all recursions from this node down, are over, and all
463 dependencies have been added in proper order in the ordered array, add
464 also the package pkg to ordered array */
465 pkg_vec_insert(ordered, pkg);
471 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
473 pkg_vec_t *all, *ordered, *visited;
479 opkg_message(conf, OPKG_INFO,
480 "Configuring unpacked packages\n");
483 all = pkg_vec_alloc();
485 pkg_hash_fetch_available(&conf->pkg_hash, all);
487 /* Reorder pkgs in order to be configured according to the Depends: tag
489 opkg_message(conf, OPKG_INFO,
490 "Reordering packages before configuring them...\n");
491 ordered = pkg_vec_alloc();
492 visited = pkg_vec_alloc();
493 for(i = 0; i < all->len; i++) {
495 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
499 ic = opkg_prep_intercepts (conf);
501 for(i = 0; i < all->len; i++) {
504 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
507 if (pkg->state_status == SS_UNPACKED) {
508 opkg_message(conf, OPKG_NOTICE,
509 "Configuring %s\n", pkg->name);
511 r = opkg_configure(conf, pkg);
513 pkg->state_status = SS_INSTALLED;
514 pkg->parent->state_status = SS_INSTALLED;
515 pkg->state_flag &= ~SF_PREFER;
523 r = opkg_finalize_intercepts (ic);
528 pkg_vec_free(ordered);
529 pkg_vec_free(visited);
534 static opkg_conf_t *global_conf;
536 static void sigint_handler(int sig)
538 signal(sig, SIG_DFL);
539 opkg_message(NULL, OPKG_NOTICE,
540 "opkg: interrupted. writing out status database\n");
541 write_status_files_if_changed(global_conf);
545 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
552 signal(SIGINT, sigint_handler);
555 * Now scan through package names and install
557 for (i=0; i < argc; i++) {
560 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
561 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
562 if (err != EINVAL && err != 0)
565 pkg_info_preinstall_check(conf);
567 for (i=0; i < argc; i++) {
569 err = opkg_install_by_name(conf, arg);
570 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
571 opkg_message(conf, OPKG_ERROR,
572 "Cannot find package %s.\n",
577 /* recheck to verify that all dependences are satisfied */
578 if (0) opkg_satisfy_all_dependences(conf);
580 opkg_configure_packages(conf, NULL);
582 write_status_files_if_changed(conf);
587 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
594 signal(SIGINT, sigint_handler);
597 for (i=0; i < argc; i++) {
600 err = opkg_prepare_url_for_install(conf, arg, &arg);
601 if (err != EINVAL && err != 0)
604 pkg_info_preinstall_check(conf);
606 for (i=0; i < argc; i++) {
608 if (conf->restrict_to_default_dest) {
609 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
613 opkg_message(conf, OPKG_NOTICE,
614 "Package %s not installed in %s\n",
615 argv[i], conf->default_dest->name);
619 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
623 opkg_upgrade_pkg(conf, pkg);
625 opkg_install_by_name(conf, arg);
629 pkg_vec_t *installed = pkg_vec_alloc();
631 pkg_info_preinstall_check(conf);
633 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
634 for (i = 0; i < installed->len; i++) {
635 pkg = installed->pkgs[i];
636 opkg_upgrade_pkg(conf, pkg);
638 pkg_vec_free(installed);
641 /* recheck to verify that all dependences are satisfied */
642 if (0) opkg_satisfy_all_dependences(conf);
644 opkg_configure_packages(conf, NULL);
646 write_status_files_if_changed(conf);
651 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
657 pkg_info_preinstall_check(conf);
658 for (i = 0; i < argc; i++) {
661 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
663 opkg_message(conf, OPKG_ERROR,
664 "Cannot find package %s.\n"
665 "Check the spelling or perhaps run 'opkg update'\n",
670 err = opkg_download_pkg(conf, pkg, ".");
673 opkg_message(conf, OPKG_ERROR,
674 "Failed to download %s\n", pkg->name);
676 opkg_message(conf, OPKG_NOTICE,
677 "Downloaded %s as %s\n",
678 pkg->name, pkg->local_filename);
686 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
689 pkg_vec_t *available;
691 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
693 char *pkg_name = NULL;
699 available = pkg_vec_alloc();
700 pkg_hash_fetch_available(&conf->pkg_hash, available);
701 for (i=0; i < available->len; i++) {
702 pkg = available->pkgs[i];
703 /* if we have package name or pattern and pkg does not match, then skip it */
704 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
706 if (pkg->description) {
707 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
709 desc_short[0] = '\0';
711 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
712 newline = strchr(desc_short, '\n');
717 version_str = pkg_version_str_alloc(pkg);
718 opkg_cb_list(pkg->name,desc_short,
725 pkg_vec_free(available);
731 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
734 pkg_vec_t *available;
736 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
738 char *pkg_name = NULL;
744 available = pkg_vec_alloc();
745 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
746 for (i=0; i < available->len; i++) {
747 pkg = available->pkgs[i];
748 /* if we have package name or pattern and pkg does not match, then skip it */
749 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
751 if (pkg->description) {
752 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
754 desc_short[0] = '\0';
756 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
757 newline = strchr(desc_short, '\n');
762 version_str = pkg_version_str_alloc(pkg);
763 opkg_cb_list(pkg->name,desc_short,
774 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
777 pkg_vec_t *available;
779 char *pkg_name = NULL;
780 char **pkg_fields = NULL;
782 char *buff ; // = (char *)malloc(1);
788 pkg_fields = &argv[1];
792 available = pkg_vec_alloc();
794 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
796 pkg_hash_fetch_available(&conf->pkg_hash, available);
797 for (i=0; i < available->len; i++) {
798 pkg = available->pkgs[i];
799 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
803 buff = pkg_formatted_info(pkg);
805 if (opkg_cb_status) opkg_cb_status(pkg->name,
810 We should not forget that actually the pointer is allocated.
811 We need to free it :) ( Thanks florian for seeing the error )
815 if (conf->verbosity > 1) {
816 conffile_list_elt_t *iter;
817 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
818 conffile_t *cf = iter->data;
819 int modified = conffile_has_been_modified(conf, cf);
820 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
821 cf->name, cf->value, modified);
825 pkg_vec_free(available);
830 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
832 return opkg_info_status_cmd(conf, argc, argv, 0);
835 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
837 return opkg_info_status_cmd(conf, argc, argv, 1);
840 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
845 char *pkg_name = NULL;
849 err = opkg_configure_packages (conf, pkg_name);
852 err = opkg_configure_packages (conf, NULL);
855 write_status_files_if_changed(conf);
860 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
866 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
867 err = glob(globpattern, 0, NULL, &globbuf);
873 opkg_message(conf, OPKG_NOTICE,
874 "The following packages in %s will now be installed.\n",
876 for (i = 0; i < globbuf.gl_pathc; i++) {
877 opkg_message(conf, OPKG_NOTICE,
878 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
880 opkg_message(conf, OPKG_NOTICE, "\n");
881 for (i = 0; i < globbuf.gl_pathc; i++) {
882 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
884 err = unlink(globbuf.gl_pathv[i]);
886 opkg_message(conf, OPKG_ERROR,
887 "%s: ERROR: failed to unlink %s: %s\n",
888 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
898 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
902 pkg_t *pkg_to_remove;
903 pkg_vec_t *available;
904 char *pkg_name = NULL;
906 signal(SIGINT, sigint_handler);
908 // ENH: Add the "no pkg removed" just in case.
912 available = pkg_vec_alloc();
913 pkg_info_preinstall_check(conf);
915 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
916 for (i=0; i < argc; i++) {
917 pkg_name = malloc(strlen(argv[i])+2);
918 strcpy(pkg_name,argv[i]);
919 for (a=0; a < available->len; a++) {
920 pkg = available->pkgs[a];
921 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
924 if (conf->restrict_to_default_dest) {
925 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
929 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
933 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
936 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
937 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
940 opkg_remove_pkg(conf, pkg_to_remove,0);
945 pkg_vec_free(available);
947 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
949 int flagged_pkg_count = 0;
952 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
954 for (i = 0; i < installed_pkgs->len; i++) {
955 pkg_t *pkg = installed_pkgs->pkgs[i];
956 if (pkg->state_flag & SF_USER) {
959 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
960 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
963 if (!flagged_pkg_count) {
964 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
965 "so refusing to uninstall unflagged non-leaf packages\n");
969 /* find packages not flagged SF_USER (i.e., installed to
970 * satisfy a dependence) and not having any dependents, and
974 for (i = 0; i < installed_pkgs->len; i++) {
975 pkg_t *pkg = installed_pkgs->pkgs[i];
976 if (!(pkg->state_flag & SF_USER)
977 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
979 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
980 opkg_remove_pkg(conf, pkg,0);
985 pkg_vec_free(installed_pkgs);
989 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
991 write_status_files_if_changed(conf);
995 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1001 signal(SIGINT, sigint_handler);
1003 pkg_info_preinstall_check(conf);
1005 for (i=0; i < argc; i++) {
1006 if (conf->restrict_to_default_dest) {
1007 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1009 conf->default_dest);
1011 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1015 opkg_message(conf, OPKG_ERROR,
1016 "Package %s is not installed.\n", argv[i]);
1019 opkg_purge_pkg(conf, pkg);
1022 write_status_files_if_changed(conf);
1026 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1030 const char *flags = argv[0];
1033 signal(SIGINT, sigint_handler);
1035 for (i=1; i < argc; i++) {
1036 if (conf->restrict_to_default_dest) {
1037 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1039 conf->default_dest);
1041 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1045 opkg_message(conf, OPKG_ERROR,
1046 "Package %s is not installed.\n", argv[i]);
1049 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1050 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1051 pkg->state_flag = pkg_state_flag_from_str(flags);
1053 /* pb_ asked this feature 03292004 */
1054 /* Actually I will use only this two, but this is an open for various status */
1055 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1056 pkg->state_status = pkg_state_status_from_str(flags);
1058 opkg_state_changed++;
1059 opkg_message(conf, OPKG_NOTICE,
1060 "Setting flags for package %s to %s\n",
1064 write_status_files_if_changed(conf);
1068 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1071 str_list_t *installed_files;
1072 str_list_elt_t *iter;
1074 size_t buff_len = 8192;
1078 buff = (char *)malloc(buff_len);
1079 if ( buff == NULL ) {
1080 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1088 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1091 opkg_message(conf, OPKG_ERROR,
1092 "Package %s not installed.\n", argv[0]);
1096 installed_files = pkg_get_installed_files(pkg);
1097 pkg_version = pkg_version_str_alloc(pkg);
1101 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1102 pkg->name, pkg_version, pkg->dest->name) + 1;
1103 if (used_len > buff_len) {
1105 buff = realloc (buff, buff_len);
1108 for (iter = installed_files->head; iter; iter = iter->next) {
1109 used_len += strlen (iter->data) + 1;
1110 while (buff_len <= used_len) {
1112 buff = realloc (buff, buff_len);
1114 strncat(buff, iter->data, buff_len);
1115 strncat(buff, "\n", buff_len);
1117 if (opkg_cb_list) opkg_cb_list(pkg->name,
1119 pkg_version_str_alloc(pkg),
1126 pkg_free_installed_files(pkg);
1131 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1135 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1136 const char *rel_str = "depends on";
1139 pkg_info_preinstall_check(conf);
1141 if (conf->query_all)
1142 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1144 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1145 for (i = 0; i < argc; i++) {
1146 const char *target = argv[i];
1149 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1151 for (j = 0; j < available_pkgs->len; j++) {
1152 pkg_t *pkg = available_pkgs->pkgs[j];
1153 if (fnmatch(target, pkg->name, 0) == 0) {
1155 int count = pkg->depends_count + pkg->pre_depends_count;
1156 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1157 target, pkg->architecture, rel_str);
1158 for (k = 0; k < count; k++) {
1159 compound_depend_t *cdepend = &pkg->depends[k];
1161 for (l = 0; l < cdepend->possibility_count; l++) {
1162 depend_t *possibility = cdepend->possibilities[l];
1163 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1164 if (conf->verbosity > 0) {
1165 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1166 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1167 if (possibility->version) {
1168 char *typestr = NULL;
1169 switch (possibility->constraint) {
1170 case NONE: typestr = "none"; break;
1171 case EARLIER: typestr = "<"; break;
1172 case EARLIER_EQUAL: typestr = "<="; break;
1173 case EQUAL: typestr = "="; break;
1174 case LATER_EQUAL: typestr = ">="; break;
1175 case LATER: typestr = ">"; break;
1177 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1181 opkg_message(conf, OPKG_ERROR, "\n");
1187 pkg_vec_free(available_pkgs);
1192 enum what_field_type {
1201 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1205 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1206 const char *rel_str = NULL;
1210 switch (what_field_type) {
1211 case WHATDEPENDS: rel_str = "depends on"; break;
1212 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1213 case WHATSUGGESTS: rel_str = "suggests"; break;
1214 case WHATRECOMMENDS: rel_str = "recommends"; break;
1215 case WHATPROVIDES: rel_str = "provides"; break;
1216 case WHATREPLACES: rel_str = "replaces"; break;
1219 if (conf->query_all)
1220 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1222 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1224 /* mark the root set */
1225 pkg_vec_clear_marks(available_pkgs);
1226 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1227 for (i = 0; i < argc; i++) {
1228 const char *dependee_pattern = argv[i];
1229 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1231 for (i = 0; i < available_pkgs->len; i++) {
1232 pkg_t *pkg = available_pkgs->pkgs[i];
1233 if (pkg->state_flag & SF_MARKED) {
1234 /* mark the parent (abstract) package */
1235 pkg_mark_provides(pkg);
1236 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1240 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1245 for (j = 0; j < available_pkgs->len; j++) {
1246 pkg_t *pkg = available_pkgs->pkgs[j];
1248 int count = ((what_field_type == WHATCONFLICTS)
1249 ? pkg->conflicts_count
1250 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1251 /* skip this package if it is already marked */
1252 if (pkg->parent->state_flag & SF_MARKED) {
1255 for (k = 0; k < count; k++) {
1256 compound_depend_t *cdepend =
1257 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1259 for (l = 0; l < cdepend->possibility_count; l++) {
1260 depend_t *possibility = cdepend->possibilities[l];
1261 if (possibility->pkg->state_flag & SF_MARKED) {
1262 /* mark the depending package so we won't visit it again */
1263 pkg->state_flag |= SF_MARKED;
1264 pkg_mark_provides(pkg);
1267 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1268 if (conf->verbosity > 0) {
1269 char *ver = pkg_version_str_alloc(pkg);
1270 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1271 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1272 if (possibility->version) {
1273 char *typestr = NULL;
1274 switch (possibility->constraint) {
1275 case NONE: typestr = "none"; break;
1276 case EARLIER: typestr = "<"; break;
1277 case EARLIER_EQUAL: typestr = "<="; break;
1278 case EQUAL: typestr = "="; break;
1279 case LATER_EQUAL: typestr = ">="; break;
1280 case LATER: typestr = ">"; break;
1282 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1285 if (!pkg_dependence_satisfiable(conf, possibility))
1286 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1288 opkg_message(conf, OPKG_NOTICE, "\n");
1296 } while (changed && recursive);
1297 pkg_vec_free(available_pkgs);
1303 static int pkg_mark_provides(pkg_t *pkg)
1305 int provides_count = pkg->provides_count;
1306 abstract_pkg_t **provides = pkg->provides;
1308 pkg->parent->state_flag |= SF_MARKED;
1309 for (i = 0; i < provides_count; i++) {
1310 provides[i]->state_flag |= SF_MARKED;
1315 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1317 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1319 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1321 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1324 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1326 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1329 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1331 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1334 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1336 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1339 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1343 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1344 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1347 pkg_info_preinstall_check(conf);
1349 if (conf->query_all)
1350 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1352 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1353 for (i = 0; i < argc; i++) {
1354 const char *target = argv[i];
1357 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1359 for (j = 0; j < available_pkgs->len; j++) {
1360 pkg_t *pkg = available_pkgs->pkgs[j];
1362 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1363 for (k = 0; k < count; k++) {
1364 abstract_pkg_t *apkg =
1365 ((what_field_type == WHATPROVIDES)
1367 : pkg->replaces[k]);
1368 if (fnmatch(target, apkg->name, 0) == 0) {
1369 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1370 if (strcmp(target, apkg->name) != 0)
1371 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1372 opkg_message(conf, OPKG_ERROR, "\n");
1377 pkg_vec_free(available_pkgs);
1382 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1384 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1387 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1389 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1392 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1396 pkg_vec_t *installed;
1398 str_list_t *installed_files;
1399 str_list_elt_t *iter;
1400 char *installed_file;
1406 installed = pkg_vec_alloc();
1407 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1409 for (i=0; i < installed->len; i++) {
1410 pkg = installed->pkgs[i];
1412 installed_files = pkg_get_installed_files(pkg);
1414 for (iter = installed_files->head; iter; iter = iter->next) {
1415 installed_file = iter->data;
1416 if (fnmatch(argv[0], installed_file, 0)==0) {
1417 if (opkg_cb_list) opkg_cb_list(pkg->name,
1419 pkg_version_str_alloc(pkg),
1420 pkg->state_status, p_userdata);
1424 pkg_free_installed_files(pkg);
1427 /* XXX: CLEANUP: It's not obvious from the name of
1428 pkg_hash_fetch_all_installed that we need to call
1429 pkg_vec_free to avoid a memory leak. */
1430 pkg_vec_free(installed);
1435 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1438 /* this is a bit gross */
1440 parseVersion(&p1, argv[0]);
1441 parseVersion(&p2, argv[2]);
1442 return pkg_version_satisfied(&p1, &p2, argv[1]);
1444 opkg_message(conf, OPKG_ERROR,
1445 "opkg compare_versions <v1> <op> <v2>\n"
1446 "<op> is one of <= >= << >> =\n");
1451 #ifndef HOST_CPU_STR
1452 #define HOST_CPU_STR__(X) #X
1453 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1454 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1457 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1459 nv_pair_list_elt_t *l;
1461 l = conf->arch_list.head;
1463 nv_pair_t *nv = l->data;
1464 printf("arch %s %s\n", nv->name, nv->value);