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);
76 /* XXX: CLEANUP: The usage strings should be incorporated into this
77 array for easier maintenance */
78 static opkg_cmd_t cmds[] = {
79 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
80 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
81 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
82 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
83 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
84 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
85 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
86 {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd},
87 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
88 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
89 {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
90 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
91 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
92 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
93 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
94 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
95 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
96 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
97 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
98 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
99 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
100 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
101 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
102 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
103 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
104 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
105 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
106 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
107 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
110 int opkg_state_changed;
111 static void write_status_files_if_changed(opkg_conf_t *conf)
113 if (opkg_state_changed && !conf->noaction) {
114 opkg_message(conf, OPKG_INFO,
115 " writing status file\n");
116 opkg_conf_write_status_files(conf);
117 pkg_write_changed_filelists(conf);
119 opkg_message(conf, OPKG_NOTICE, "Nothing to be done\n");
124 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
126 opkg_cmd_t *opkg_cmd_find(const char *name)
131 for (i=0; i < num_cmds; i++) {
133 if (strcmp(name, cmd->name) == 0) {
141 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
144 p_userdata = userdata;
147 result = (cmd->fun)(conf, argc, argv);
150 opkg_message(conf, OPKG_NOTICE, "An error ocurred, return value: %d.\n", result);
154 reverse_error_list(&error_list);
156 opkg_message(conf, OPKG_NOTICE, "Collected errors:\n");
157 /* Here we print the errors collected and free the list */
158 while (error_list != NULL) {
159 opkg_message(conf, OPKG_NOTICE, "%s",error_list->errmsg);
160 error_list = error_list->next;
163 free_error_list(&error_list);
171 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
177 pkg_src_list_elt_t *iter;
181 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
183 if (! file_is_dir(lists_dir)) {
184 if (file_exists(lists_dir)) {
185 opkg_message(conf, OPKG_ERROR,
186 "%s: ERROR: %s exists, but is not a directory\n",
187 __FUNCTION__, lists_dir);
191 err = file_mkdir_hier(lists_dir, 0755);
193 opkg_message(conf, OPKG_ERROR,
194 "%s: ERROR: failed to make directory %s: %s\n",
195 __FUNCTION__, lists_dir, strerror(errno));
204 tmp = strdup ("/tmp/opkg.XXXXXX");
206 if (mkdtemp (tmp) == NULL) {
212 for (iter = conf->pkg_src_list.head; iter; iter = iter->next) {
213 char *url, *list_file_name;
217 if (src->extra_data) /* debian style? */
218 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
219 src->gzip ? "Packages.gz" : "Packages");
221 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
223 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
228 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
229 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
231 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
232 in = fopen (tmp_file_name, "r");
233 out = fopen (list_file_name, "w");
242 unlink (tmp_file_name);
245 err = opkg_download(conf, url, list_file_name, NULL, NULL);
249 opkg_message(conf, OPKG_NOTICE,
250 "Updated list of available packages in %s\n",
256 /* download detached signitures to verify the package lists */
257 /* get the url for the sig file */
258 if (src->extra_data) /* debian style? */
259 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
262 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
264 /* create temporary file for it */
267 sprintf_alloc (&tmp_file_name, "%s/%s", tmp, "Packages.sig");
269 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
272 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
275 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
277 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
279 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
281 unlink (tmp_file_name);
282 free (tmp_file_name);
285 opkg_message (conf, OPKG_NOTICE, "Signiture check for %s skipped "
286 "because GPG support was not enabled in this build\n", src->name);
288 free(list_file_name);
298 /* scan the args passed and cache the local filenames of the packages */
299 int opkg_multiple_files_scan(opkg_conf_t *conf, int argc, char **argv)
305 * First scan through package names/urls
306 * For any urls, download the packages and install in database.
307 * For any files, install package info in database.
309 for (i = 0; i < argc; i ++) {
310 char *filename = argv [i];
311 //char *tmp = basename (tmp);
312 //int tmplen = strlen (tmp);
314 //if (strcmp (tmp + (tmplen - strlen (OPKG_PKG_EXTENSION)), OPKG_PKG_EXTENSION) != 0)
316 //if (strcmp (tmp + (tmplen - strlen (DPKG_PKG_EXTENSION)), DPKG_PKG_EXTENSION) != 0)
319 opkg_message(conf, OPKG_DEBUG2, "Debug mfs: %s \n",filename );
321 err = opkg_prepare_url_for_install(conf, filename, &argv[i]);
328 struct opkg_intercept
334 typedef struct opkg_intercept *opkg_intercept_t;
336 opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
338 opkg_intercept_t ctx;
342 ctx = malloc (sizeof (*ctx));
343 ctx->oldpath = strdup (getenv ("PATH"));
345 sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
346 setenv ("PATH", newpath, 1);
351 sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
352 if (mkdir (ctx->statedir, 0770) < 0) {
353 if (errno == EEXIST) {
354 free (ctx->statedir);
358 perror (ctx->statedir);
361 setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
365 int opkg_finalize_intercepts(opkg_intercept_t ctx)
371 setenv ("PATH", ctx->oldpath, 1);
374 dir = opendir (ctx->statedir);
377 while (de = readdir (dir), de != NULL) {
380 if (de->d_name[0] == '.')
383 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
384 if (access (path, X_OK) == 0) {
393 perror (ctx->statedir);
395 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
399 free (ctx->statedir);
405 /* For package pkg do the following: If it is already visited, return. If not,
406 add it in visited list and recurse to its deps. Finally, add it to ordered
408 pkg_vec all contains all available packages in repos.
409 pkg_vec visited contains packages already visited by this function, and is
410 used to end recursion and avoid an infinite loop on graph cycles.
411 pkg_vec ordered will finally contain the ordered set of packages.
413 int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
414 pkg_vec_t *visited, pkg_vec_t *ordered)
419 compound_depend_t * compound_depend;
420 depend_t ** possible_satisfiers;
421 abstract_pkg_t *abpkg;
422 abstract_pkg_t **dependents;
424 /* If it's just an available package, that is, not installed and not even
426 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
427 would do here. However, if there is an intermediate node (pkg) that is
428 configured and installed between two unpacked packages, the latter
429 won't be properly reordered, unless all installed/unpacked pkgs are
431 if (pkg->state_status == SS_NOT_INSTALLED)
434 /* If the package has already been visited (by this function), skip it */
435 for(j = 0; j < visited->len; j++)
436 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
437 opkg_message(conf, OPKG_INFO,
438 " pkg: %s already visited\n", pkg->name);
442 pkg_vec_insert(visited, pkg);
444 count = pkg->pre_depends_count + pkg->depends_count + \
445 pkg->recommends_count + pkg->suggests_count;
447 opkg_message(conf, OPKG_INFO,
448 " pkg: %s\n", pkg->name);
450 /* Iterate over all the dependencies of pkg. For each one, find a package
451 that is either installed or unpacked and satisfies this dependency.
452 (there should only be one such package per dependency installed or
453 unpacked). Then recurse to the dependency package */
454 for (j=0; j < count ; j++) {
455 compound_depend = &pkg->depends[j];
456 possible_satisfiers = compound_depend->possibilities;
457 for (k=0; k < compound_depend->possibility_count ; k++) {
458 abpkg = possible_satisfiers[k]->pkg;
459 dependents = abpkg->provided_by->pkgs;
461 if (dependents != NULL)
462 while (dependents [l] != NULL && l < abpkg->provided_by->len) {
463 opkg_message(conf, OPKG_INFO,
464 " Descending on pkg: %s\n",
465 dependents [l]->name);
467 /* find whether dependent l is installed or unpacked,
468 * and then find which package in the list satisfies it */
469 for(m = 0; m < all->len; m++) {
471 if ( dep->state_status != SS_NOT_INSTALLED)
472 if ( ! strcmp(dep->name, dependents[l]->name)) {
473 opkg_recurse_pkgs_in_order(conf, dep, all,
475 /* Stop the outer loop */
476 l = abpkg->provided_by->len;
477 /* break from the inner loop */
486 /* When all recursions from this node down, are over, and all
487 dependencies have been added in proper order in the ordered array, add
488 also the package pkg to ordered array */
489 pkg_vec_insert(ordered, pkg);
495 int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
497 pkg_vec_t *all, *ordered, *visited;
503 opkg_message(conf, OPKG_INFO,
504 "Configuring unpacked packages\n");
507 all = pkg_vec_alloc();
509 pkg_hash_fetch_available(&conf->pkg_hash, all);
511 /* Reorder pkgs in order to be configured according to the Depends: tag
513 opkg_message(conf, OPKG_INFO,
514 "Reordering packages before configuring them...\n");
515 ordered = pkg_vec_alloc();
516 visited = pkg_vec_alloc();
517 for(i = 0; i < all->len; i++) {
519 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
523 ic = opkg_prep_intercepts (conf);
525 for(i = 0; i < all->len; i++) {
528 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
531 if (pkg->state_status == SS_UNPACKED) {
532 opkg_message(conf, OPKG_NOTICE,
533 "Configuring %s\n", pkg->name);
535 r = opkg_configure(conf, pkg);
537 pkg->state_status = SS_INSTALLED;
538 pkg->parent->state_status = SS_INSTALLED;
539 pkg->state_flag &= ~SF_PREFER;
547 r = opkg_finalize_intercepts (ic);
552 pkg_vec_free(ordered);
553 pkg_vec_free(visited);
558 static opkg_conf_t *global_conf;
560 static void sigint_handler(int sig)
562 signal(sig, SIG_DFL);
563 opkg_message(NULL, OPKG_NOTICE,
564 "opkg: interrupted. writing out status database\n");
565 write_status_files_if_changed(global_conf);
569 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
576 signal(SIGINT, sigint_handler);
579 * Now scan through package names and install
581 for (i=0; i < argc; i++) {
584 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
585 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
586 if (err != EINVAL && err != 0)
589 pkg_info_preinstall_check(conf);
591 for (i=0; i < argc; i++) {
593 err = opkg_install_by_name(conf, arg);
594 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
595 opkg_message(conf, OPKG_ERROR,
596 "Cannot find package %s.\n"
597 "Check the spelling or perhaps run 'opkg update'\n",
602 /* recheck to verify that all dependences are satisfied */
603 if (0) opkg_satisfy_all_dependences(conf);
605 opkg_configure_packages(conf, NULL);
607 write_status_files_if_changed(conf);
612 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
619 signal(SIGINT, sigint_handler);
622 for (i=0; i < argc; i++) {
625 err = opkg_prepare_url_for_install(conf, arg, &arg);
626 if (err != EINVAL && err != 0)
629 pkg_info_preinstall_check(conf);
631 for (i=0; i < argc; i++) {
633 if (conf->restrict_to_default_dest) {
634 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
638 opkg_message(conf, OPKG_NOTICE,
639 "Package %s not installed in %s\n",
640 argv[i], conf->default_dest->name);
644 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
648 opkg_upgrade_pkg(conf, pkg);
650 opkg_install_by_name(conf, arg);
654 pkg_vec_t *installed = pkg_vec_alloc();
656 pkg_info_preinstall_check(conf);
658 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
659 for (i = 0; i < installed->len; i++) {
660 pkg = installed->pkgs[i];
661 opkg_upgrade_pkg(conf, pkg);
663 pkg_vec_free(installed);
666 /* recheck to verify that all dependences are satisfied */
667 if (0) opkg_satisfy_all_dependences(conf);
669 opkg_configure_packages(conf, NULL);
671 write_status_files_if_changed(conf);
676 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
682 pkg_info_preinstall_check(conf);
683 for (i = 0; i < argc; i++) {
686 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg);
688 opkg_message(conf, OPKG_ERROR,
689 "Cannot find package %s.\n"
690 "Check the spelling or perhaps run 'opkg update'\n",
695 err = opkg_download_pkg(conf, pkg, ".");
698 opkg_message(conf, OPKG_ERROR,
699 "Failed to download %s\n", pkg->name);
701 opkg_message(conf, OPKG_NOTICE,
702 "Downloaded %s as %s\n",
703 pkg->name, pkg->local_filename);
711 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
714 pkg_vec_t *available;
716 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
718 char *pkg_name = NULL;
724 available = pkg_vec_alloc();
725 pkg_hash_fetch_available(&conf->pkg_hash, available);
726 for (i=0; i < available->len; i++) {
727 pkg = available->pkgs[i];
728 /* if we have package name or pattern and pkg does not match, then skip it */
729 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
731 if (pkg->description) {
732 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
734 desc_short[0] = '\0';
736 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
737 newline = strchr(desc_short, '\n');
742 version_str = pkg_version_str_alloc(pkg);
743 opkg_cb_list(pkg->name,desc_short,
750 pkg_vec_free(available);
756 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
759 pkg_vec_t *available;
761 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
763 char *pkg_name = NULL;
769 available = pkg_vec_alloc();
770 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
771 for (i=0; i < available->len; i++) {
772 pkg = available->pkgs[i];
773 /* if we have package name or pattern and pkg does not match, then skip it */
774 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
776 if (pkg->description) {
777 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
779 desc_short[0] = '\0';
781 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
782 newline = strchr(desc_short, '\n');
787 version_str = pkg_version_str_alloc(pkg);
788 opkg_cb_list(pkg->name,desc_short,
799 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
802 pkg_vec_t *available;
804 char *pkg_name = NULL;
805 char **pkg_fields = NULL;
807 char *buff ; // = (char *)malloc(1);
813 pkg_fields = &argv[1];
817 available = pkg_vec_alloc();
819 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
821 pkg_hash_fetch_available(&conf->pkg_hash, available);
822 for (i=0; i < available->len; i++) {
823 pkg = available->pkgs[i];
824 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
828 buff = pkg_formatted_info(pkg);
830 if (opkg_cb_status) opkg_cb_status(pkg->name,
835 We should not forget that actually the pointer is allocated.
836 We need to free it :) ( Thanks florian for seeing the error )
840 if (conf->verbosity > 1) {
841 conffile_list_elt_t *iter;
842 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
843 conffile_t *cf = iter->data;
844 int modified = conffile_has_been_modified(conf, cf);
845 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
846 cf->name, cf->value, modified);
850 pkg_vec_free(available);
855 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
857 return opkg_info_status_cmd(conf, argc, argv, 0);
860 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
862 return opkg_info_status_cmd(conf, argc, argv, 1);
865 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
870 char *pkg_name = NULL;
874 err = opkg_configure_packages (conf, pkg_name);
877 err = opkg_configure_packages (conf, NULL);
880 write_status_files_if_changed(conf);
885 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
891 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
892 err = glob(globpattern, 0, NULL, &globbuf);
898 opkg_message(conf, OPKG_NOTICE,
899 "The following packages in %s will now be installed.\n",
901 for (i = 0; i < globbuf.gl_pathc; i++) {
902 opkg_message(conf, OPKG_NOTICE,
903 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
905 opkg_message(conf, OPKG_NOTICE, "\n");
906 for (i = 0; i < globbuf.gl_pathc; i++) {
907 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
909 err = unlink(globbuf.gl_pathv[i]);
911 opkg_message(conf, OPKG_ERROR,
912 "%s: ERROR: failed to unlink %s: %s\n",
913 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
923 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
927 pkg_t *pkg_to_remove;
928 pkg_vec_t *available;
929 char *pkg_name = NULL;
931 signal(SIGINT, sigint_handler);
933 // ENH: Add the "no pkg removed" just in case.
937 available = pkg_vec_alloc();
938 pkg_info_preinstall_check(conf);
940 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
941 for (i=0; i < argc; i++) {
942 pkg_name = malloc(strlen(argv[i])+2);
943 strcpy(pkg_name,argv[i]);
944 for (a=0; a < available->len; a++) {
945 pkg = available->pkgs[a];
946 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
949 if (conf->restrict_to_default_dest) {
950 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
954 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
958 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
961 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
962 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
965 opkg_remove_pkg(conf, pkg_to_remove,0);
970 pkg_vec_free(available);
972 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
974 int flagged_pkg_count = 0;
977 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
979 for (i = 0; i < installed_pkgs->len; i++) {
980 pkg_t *pkg = installed_pkgs->pkgs[i];
981 if (pkg->state_flag & SF_USER) {
984 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
985 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
988 if (!flagged_pkg_count) {
989 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
990 "so refusing to uninstall unflagged non-leaf packages\n");
994 /* find packages not flagged SF_USER (i.e., installed to
995 * satisfy a dependence) and not having any dependents, and
999 for (i = 0; i < installed_pkgs->len; i++) {
1000 pkg_t *pkg = installed_pkgs->pkgs[i];
1001 if (!(pkg->state_flag & SF_USER)
1002 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1004 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1005 opkg_remove_pkg(conf, pkg,0);
1010 pkg_vec_free(installed_pkgs);
1014 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1016 write_status_files_if_changed(conf);
1020 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1026 signal(SIGINT, sigint_handler);
1028 pkg_info_preinstall_check(conf);
1030 for (i=0; i < argc; i++) {
1031 if (conf->restrict_to_default_dest) {
1032 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1034 conf->default_dest);
1036 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1040 opkg_message(conf, OPKG_ERROR,
1041 "Package %s is not installed.\n", argv[i]);
1044 opkg_purge_pkg(conf, pkg);
1047 write_status_files_if_changed(conf);
1051 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1055 const char *flags = argv[0];
1058 signal(SIGINT, sigint_handler);
1060 for (i=1; i < argc; i++) {
1061 if (conf->restrict_to_default_dest) {
1062 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1064 conf->default_dest);
1066 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1070 opkg_message(conf, OPKG_ERROR,
1071 "Package %s is not installed.\n", argv[i]);
1074 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1075 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1076 pkg->state_flag = pkg_state_flag_from_str(flags);
1078 /* pb_ asked this feature 03292004 */
1079 /* Actually I will use only this two, but this is an open for various status */
1080 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1081 pkg->state_status = pkg_state_status_from_str(flags);
1083 opkg_state_changed++;
1084 opkg_message(conf, OPKG_NOTICE,
1085 "Setting flags for package %s to %s\n",
1089 write_status_files_if_changed(conf);
1093 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1096 str_list_t *installed_files;
1097 str_list_elt_t *iter;
1099 size_t buff_len = 8192;
1103 buff = (char *)malloc(buff_len);
1104 if ( buff == NULL ) {
1105 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1113 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1116 opkg_message(conf, OPKG_ERROR,
1117 "Package %s not installed.\n", argv[0]);
1121 installed_files = pkg_get_installed_files(pkg);
1122 pkg_version = pkg_version_str_alloc(pkg);
1126 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1127 pkg->name, pkg_version, pkg->dest->name) + 1;
1128 if (used_len > buff_len) {
1130 buff = realloc (buff, buff_len);
1133 for (iter = installed_files->head; iter; iter = iter->next) {
1134 used_len += strlen (iter->data) + 1;
1135 while (buff_len <= used_len) {
1137 buff = realloc (buff, buff_len);
1139 strncat(buff, iter->data, buff_len);
1140 strncat(buff, "\n", buff_len);
1142 if (opkg_cb_list) opkg_cb_list(pkg->name,
1144 pkg_version_str_alloc(pkg),
1151 pkg_free_installed_files(pkg);
1156 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1160 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1161 const char *rel_str = "depends on";
1164 pkg_info_preinstall_check(conf);
1166 if (conf->query_all)
1167 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1169 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1170 for (i = 0; i < argc; i++) {
1171 const char *target = argv[i];
1174 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1176 for (j = 0; j < available_pkgs->len; j++) {
1177 pkg_t *pkg = available_pkgs->pkgs[j];
1178 if (fnmatch(target, pkg->name, 0) == 0) {
1180 int count = pkg->depends_count + pkg->pre_depends_count;
1181 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1182 target, pkg->architecture, rel_str);
1183 for (k = 0; k < count; k++) {
1184 compound_depend_t *cdepend = &pkg->depends[k];
1186 for (l = 0; l < cdepend->possibility_count; l++) {
1187 depend_t *possibility = cdepend->possibilities[l];
1188 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1189 if (conf->verbosity > 0) {
1190 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1191 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1192 if (possibility->version) {
1193 char *typestr = NULL;
1194 switch (possibility->constraint) {
1195 case NONE: typestr = "none"; break;
1196 case EARLIER: typestr = "<"; break;
1197 case EARLIER_EQUAL: typestr = "<="; break;
1198 case EQUAL: typestr = "="; break;
1199 case LATER_EQUAL: typestr = ">="; break;
1200 case LATER: typestr = ">"; break;
1202 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1206 opkg_message(conf, OPKG_ERROR, "\n");
1212 pkg_vec_free(available_pkgs);
1217 enum what_field_type {
1226 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1230 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1231 const char *rel_str = NULL;
1235 switch (what_field_type) {
1236 case WHATDEPENDS: rel_str = "depends on"; break;
1237 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1238 case WHATSUGGESTS: rel_str = "suggests"; break;
1239 case WHATRECOMMENDS: rel_str = "recommends"; break;
1240 case WHATPROVIDES: rel_str = "provides"; break;
1241 case WHATREPLACES: rel_str = "replaces"; break;
1244 if (conf->query_all)
1245 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1247 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1249 /* mark the root set */
1250 pkg_vec_clear_marks(available_pkgs);
1251 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1252 for (i = 0; i < argc; i++) {
1253 const char *dependee_pattern = argv[i];
1254 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1256 for (i = 0; i < available_pkgs->len; i++) {
1257 pkg_t *pkg = available_pkgs->pkgs[i];
1258 if (pkg->state_flag & SF_MARKED) {
1259 /* mark the parent (abstract) package */
1260 pkg_mark_provides(pkg);
1261 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1265 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1270 for (j = 0; j < available_pkgs->len; j++) {
1271 pkg_t *pkg = available_pkgs->pkgs[j];
1273 int count = ((what_field_type == WHATCONFLICTS)
1274 ? pkg->conflicts_count
1275 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1276 /* skip this package if it is already marked */
1277 if (pkg->parent->state_flag & SF_MARKED) {
1280 for (k = 0; k < count; k++) {
1281 compound_depend_t *cdepend =
1282 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1284 for (l = 0; l < cdepend->possibility_count; l++) {
1285 depend_t *possibility = cdepend->possibilities[l];
1286 if (possibility->pkg->state_flag & SF_MARKED) {
1287 /* mark the depending package so we won't visit it again */
1288 pkg->state_flag |= SF_MARKED;
1289 pkg_mark_provides(pkg);
1292 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1293 if (conf->verbosity > 0) {
1294 char *ver = pkg_version_str_alloc(pkg);
1295 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1296 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1297 if (possibility->version) {
1298 char *typestr = NULL;
1299 switch (possibility->constraint) {
1300 case NONE: typestr = "none"; break;
1301 case EARLIER: typestr = "<"; break;
1302 case EARLIER_EQUAL: typestr = "<="; break;
1303 case EQUAL: typestr = "="; break;
1304 case LATER_EQUAL: typestr = ">="; break;
1305 case LATER: typestr = ">"; break;
1307 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1310 if (!pkg_dependence_satisfiable(conf, possibility))
1311 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1313 opkg_message(conf, OPKG_NOTICE, "\n");
1321 } while (changed && recursive);
1322 pkg_vec_free(available_pkgs);
1328 int pkg_mark_provides(pkg_t *pkg)
1330 int provides_count = pkg->provides_count;
1331 abstract_pkg_t **provides = pkg->provides;
1333 pkg->parent->state_flag |= SF_MARKED;
1334 for (i = 0; i < provides_count; i++) {
1335 provides[i]->state_flag |= SF_MARKED;
1340 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1342 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1344 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1346 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1349 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1351 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1354 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1356 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1359 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1361 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1364 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1368 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1369 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1372 pkg_info_preinstall_check(conf);
1374 if (conf->query_all)
1375 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1377 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1378 for (i = 0; i < argc; i++) {
1379 const char *target = argv[i];
1382 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1384 for (j = 0; j < available_pkgs->len; j++) {
1385 pkg_t *pkg = available_pkgs->pkgs[j];
1387 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1388 for (k = 0; k < count; k++) {
1389 abstract_pkg_t *apkg =
1390 ((what_field_type == WHATPROVIDES)
1392 : pkg->replaces[k]);
1393 if (fnmatch(target, apkg->name, 0) == 0) {
1394 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1395 if (strcmp(target, apkg->name) != 0)
1396 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1397 opkg_message(conf, OPKG_ERROR, "\n");
1402 pkg_vec_free(available_pkgs);
1407 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1409 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1412 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1414 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1417 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1421 pkg_vec_t *installed;
1423 str_list_t *installed_files;
1424 str_list_elt_t *iter;
1425 char *installed_file;
1431 installed = pkg_vec_alloc();
1432 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1434 for (i=0; i < installed->len; i++) {
1435 pkg = installed->pkgs[i];
1437 installed_files = pkg_get_installed_files(pkg);
1439 for (iter = installed_files->head; iter; iter = iter->next) {
1440 installed_file = iter->data;
1441 if (fnmatch(argv[0], installed_file, 0)==0) {
1442 if (opkg_cb_list) opkg_cb_list(pkg->name,
1444 pkg_version_str_alloc(pkg),
1445 pkg->state_status, p_userdata);
1449 pkg_free_installed_files(pkg);
1452 /* XXX: CLEANUP: It's not obvious from the name of
1453 pkg_hash_fetch_all_installed that we need to call
1454 pkg_vec_free to avoid a memory leak. */
1455 pkg_vec_free(installed);
1460 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1463 /* this is a bit gross */
1465 parseVersion(&p1, argv[0]);
1466 parseVersion(&p2, argv[2]);
1467 return pkg_version_satisfied(&p1, &p2, argv[1]);
1469 opkg_message(conf, OPKG_ERROR,
1470 "opkg compare_versions <v1> <op> <v2>\n"
1471 "<op> is one of <= >= << >> =\n");
1476 #ifndef HOST_CPU_STR
1477 #define HOST_CPU_STR__(X) #X
1478 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1479 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1482 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1484 nv_pair_list_elt_t *l;
1486 l = conf->arch_list.head;
1488 nv_pair_t *nv = l->data;
1489 printf("arch %s %s\n", nv->name, nv->value);