X-Git-Url: https://git.librecmc.org/?p=oweals%2Fopkg-lede.git;a=blobdiff_plain;f=libopkg%2Fopkg_cmd.c;h=d1e91cbeae54bfdad58b0dfcedfcb63f79d0e065;hp=db04a4a680fbd8ace0e114bfa681febf8d01d9eb;hb=cd113c7ea9d8883d9cdc4c3e4ea4f87531737183;hpb=4b0b7ca249bfa4ecc099c2ca56527eb91776f198 diff --git a/libopkg/opkg_cmd.c b/libopkg/opkg_cmd.c index db04a4a..d1e91cb 100644 --- a/libopkg/opkg_cmd.c +++ b/libopkg/opkg_cmd.c @@ -1,4 +1,4 @@ -/* opkg_cmd.c - the itsy package management system +/* opkg_cmd.c - the opkg package management system Carl D. Worth @@ -15,357 +15,211 @@ General Public License for more details. */ -#include +#include "config.h" -#include "opkg.h" -#include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include #include "opkg_conf.h" #include "opkg_cmd.h" #include "opkg_message.h" +#include "release.h" #include "pkg.h" #include "pkg_dest.h" #include "pkg_parse.h" #include "sprintf_alloc.h" #include "pkg.h" #include "file_util.h" -#include "str_util.h" #include "libbb/libbb.h" - -#include - - +#include "opkg_utils.h" +#include "opkg_defines.h" #include "opkg_download.h" #include "opkg_install.h" #include "opkg_upgrade.h" #include "opkg_remove.h" #include "opkg_configure.h" -#include "opkg_message.h" +#include "xsystem.h" -#ifdef OPKG_LIB -#include "libopkg.h" -static void *p_userdata = NULL; -#endif - -static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv); -static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv); - -/* XXX: CLEANUP: The usage strings should be incorporated into this - array for easier maintenance */ -static opkg_cmd_t cmds[] = { - {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd}, - {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd}, - {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd}, - {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd}, - {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd}, - {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd}, - {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd}, - {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd}, - {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd}, - {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd}, - {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd}, - {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd}, - {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd}, - {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd}, - {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd}, - {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd}, - {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd}, - {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd}, - {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd}, - {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd}, - {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd}, - {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd}, - {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd}, - {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd}, - {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd}, - {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd}, - {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd}, - {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd}, - {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd}, -}; - -int opkg_state_changed; -static void write_status_files_if_changed(opkg_conf_t *conf) +static void +print_pkg(pkg_t *pkg) { - if (opkg_state_changed && !conf->noaction) { - opkg_message(conf, OPKG_INFO, - " writing status file\n"); - opkg_conf_write_status_files(conf); - pkg_write_changed_filelists(conf); - } else { - opkg_message(conf, OPKG_NOTICE, "Nothing to be done\n"); - } + char *version = pkg_version_str_alloc(pkg); + if (pkg->description) + printf("%s - %s - %s\n", pkg->name, version, pkg->description); + else + printf("%s - %s\n", pkg->name, version); + free(version); } +int opkg_state_changed; -static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t); - -opkg_cmd_t *opkg_cmd_find(const char *name) +static void +write_status_files_if_changed(void) { - int i; - opkg_cmd_t *cmd; - - for (i=0; i < num_cmds; i++) { - cmd = &cmds[i]; - if (strcmp(name, cmd->name) == 0) { - return cmd; - } + if (opkg_state_changed && !conf->noaction) { + opkg_msg(INFO, "Writing status file.\n"); + opkg_conf_write_status_files(); + pkg_write_changed_filelists(); + } else { + opkg_msg(DEBUG, "Nothing to be done.\n"); } - - return NULL; } -#ifdef OPKG_LIB -int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata) +static void +sigint_handler(int sig) { - int result; - p_userdata = userdata; - - - result = (cmd->fun)(conf, argc, argv); - - if ( result != 0 ) { - opkg_message(conf, OPKG_NOTICE, "An error ocurred, return value: %d.\n", result); - } - - if ( error_list ) { - reverse_error_list(&error_list); - - opkg_message(conf, OPKG_NOTICE, "Collected errors:\n"); - /* Here we print the errors collected and free the list */ - while (error_list != NULL) { - opkg_message(conf, OPKG_NOTICE, "%s",error_list->errmsg); - error_list = error_list->next; - - } - free_error_list(&error_list); - - } - - p_userdata = NULL; - return result; -} -#else -int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv) -{ - return (cmd->fun)(conf, argc, argv); + signal(sig, SIG_DFL); + opkg_msg(NOTICE, "Interrupted. Writing out status database.\n"); + write_status_files_if_changed(); + exit(128 + sig); } -#endif -static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_update_cmd(int argc, char **argv) { + char *tmp; int err; int failures; char *lists_dir; pkg_src_list_elt_t *iter; pkg_src_t *src; - + sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir); - + if (! file_is_dir(lists_dir)) { if (file_exists(lists_dir)) { - opkg_message(conf, OPKG_ERROR, - "%s: ERROR: %s exists, but is not a directory\n", - __FUNCTION__, lists_dir); + opkg_msg(ERROR, "%s exists, but is not a directory.\n", + lists_dir); free(lists_dir); - return EINVAL; + return -1; } err = file_mkdir_hier(lists_dir, 0755); if (err) { - opkg_message(conf, OPKG_ERROR, - "%s: ERROR: failed to make directory %s: %s\n", - __FUNCTION__, lists_dir, strerror(errno)); free(lists_dir); - return EINVAL; - } - } + return -1; + } + } failures = 0; - for (iter = conf->pkg_src_list.head; iter; iter = iter->next) { + + sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir); + if (mkdtemp (tmp) == NULL) { + opkg_perror(ERROR, "Failed to make temp dir %s", conf->tmp_dir); + return -1; + } + + + for (iter = void_list_first(&conf->dist_src_list); iter; iter = void_list_next(&conf->dist_src_list, iter)) { char *url, *list_file_name; - src = iter->data; + src = (pkg_src_t *)iter->data; - if (src->extra_data) /* debian style? */ - sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data, - src->gzip ? "Packages.gz" : "Packages"); - else - sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages"); + sprintf_alloc(&url, "%s/dists/%s/Release", src->value, src->name); sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name); - if (src->gzip) { - char *tmp; - char *tmp_file_name; - FILE *in, *out; - - tmp = strdup ("/tmp/opkg.XXXXXX"); - - if (mkdtemp (tmp) == NULL) { - perror ("mkdtemp"); - failures++; - continue; - } - - sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name); - err = opkg_download(conf, url, tmp_file_name); - if (err == 0) { - opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url); - in = fopen (tmp_file_name, "r"); - out = fopen (list_file_name, "w"); - if (in && out) - unzip (in, out); - else - err = 1; - if (in) - fclose (in); - if (out) - fclose (out); - unlink (tmp_file_name); - rmdir (tmp); - free (tmp); - } - } else - err = opkg_download(conf, url, list_file_name); - if (err) { - failures++; - } else { - opkg_message(conf, OPKG_NOTICE, - "Updated list of available packages in %s\n", - list_file_name); + err = opkg_download(url, list_file_name, NULL, NULL, 0); + if (!err) { + opkg_msg(NOTICE, "Downloaded release files for dist %s.\n", + src->name); + release_t *release = release_new(); + err = release_init_from_file(release, list_file_name); + if (!err) { + if (!release_comps_supported(release, src->extra_data)) + err = -1; + } + if (!err) { + err = release_download(release, src, lists_dir, tmp); + } + release_deinit(release); + if (err) + unlink(list_file_name); } + + if (err) + failures++; + + free(list_file_name); free(url); + } + + for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) { + char *url, *list_file_name; + + src = (pkg_src_t *)iter->data; + + if (src->extra_data && strcmp(src->extra_data, "__dummy__ ")) + continue; - /* download detached signitures to verify the package lists */ - /* get the url for the sig file */ if (src->extra_data) /* debian style? */ sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data, - "Packages.sig"); + src->gzip ? "Packages.gz" : "Packages"); else - sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig"); - - /* create temporary dir for it */ - char *tmp, *tmp_file_name; - tmp = strdup ("/tmp/opkg.XXXXXX"); - if (mkdtemp (tmp) == NULL) { - perror ("mkdtemp"); - failures++; - continue; - } - sprintf_alloc (&tmp_file_name, "%s/%s", tmp, "Packages.sig"); + sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages"); - err = opkg_download(conf, url, tmp_file_name); - if (err) { - failures++; - opkg_message (conf, OPKG_NOTICE, "Signature check failed\n"); + sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name); + if (opkg_download(url, list_file_name, NULL, NULL, 0)) { + failures++; } else { - int err; - err = opkg_verify_file (list_file_name, tmp_file_name); - if (err == 0) - opkg_message (conf, OPKG_NOTICE, "Signature check passed\n"); - else - opkg_message (conf, OPKG_NOTICE, "Signature check failed\n"); + opkg_msg(NOTICE, "Updated list of available packages in %s.\n", + list_file_name); } - unlink (tmp_file_name); - unlink (tmp); - free (tmp_file_name); - - free (url); + free(url); +#if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) + if (conf->check_signature) { + /* download detached signitures to verify the package lists */ + /* get the url for the sig file */ + if (src->extra_data) /* debian style? */ + sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data, + "Packages.sig"); + else + sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig"); + + /* create temporary file for it */ + char *tmp_file_name; + + /* Put the signature in the right place */ + sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name); + + err = opkg_download(url, tmp_file_name, NULL, NULL, 0); + if (err) { + failures++; + opkg_msg(NOTICE, "Signature check failed.\n"); + } else { + err = opkg_verify_file (list_file_name, tmp_file_name); + if (err == 0) + opkg_msg(NOTICE, "Signature check passed.\n"); + else + opkg_msg(NOTICE, "Signature check failed.\n"); + } + if (err) { + /* The signature was wrong so delete it */ + opkg_msg(NOTICE, "Remove wrong Signature file.\n"); + unlink (tmp_file_name); + unlink (list_file_name); + } + /* We shouldn't unlink the signature ! */ + // unlink (tmp_file_name); + free (tmp_file_name); + free (url); + } +#else + // Do nothing +#endif free(list_file_name); } + rmdir (tmp); + free (tmp); free(lists_dir); -#ifdef CONFIG_CLEAR_SW_INSTALL_FLAG -#warning here - /* clear SW_INSTALL on any package where state is SS_NOT_INSTALLED. - * this is a hack to work around poor bookkeeping in old opkg upgrade code - * -Jamey 3/1/03 - */ - { - int i; - int changed = 0; - pkg_vec_t *available = pkg_vec_alloc(); - pkg_hash_fetch_available(&conf->pkg_hash, available); - opkg_message(conf, OPKG_DEBUG, "Clearing SW_INSTALL for SS_NOT_INSTALLED packages.\n"); - for (i = 0; i < available->len; i++) { - pkg_t *pkg = available->pkgs[i]; - if (pkg->state_want == SW_INSTALL && pkg->state_status == SS_NOT_INSTALLED) { - opkg_message(conf, OPKG_DEBUG, "Clearing SW_INSTALL on package %s.\n", pkg->name); - pkg->state_want = SW_UNKNOWN; - changed = 1; - } - } - pkg_vec_free(available); - if (changed) { - write_status_files_if_changed(conf); - } - } -#endif - return failures; } -/* scan the args passed and cache the local filenames of the packages */ -int opkg_multiple_files_scan(opkg_conf_t *conf, int argc, char **argv) -{ - int i; - int err; - - /* - * First scan through package names/urls - * For any urls, download the packages and install in database. - * For any files, install package info in database. - */ - for (i = 0; i < argc; i ++) { - char *filename = argv [i]; - //char *tmp = basename (tmp); - //int tmplen = strlen (tmp); - - //if (strcmp (tmp + (tmplen - strlen (OPKG_PKG_EXTENSION)), OPKG_PKG_EXTENSION) != 0) - // continue; - //if (strcmp (tmp + (tmplen - strlen (DPKG_PKG_EXTENSION)), DPKG_PKG_EXTENSION) != 0) - // continue; - - opkg_message(conf, OPKG_DEBUG2, "Debug mfs: %s \n",filename ); - - err = opkg_prepare_url_for_install(conf, filename, &argv[i]); - if (err) - return err; - } - return 0; -} - struct opkg_intercept { char *oldpath; @@ -374,38 +228,36 @@ struct opkg_intercept typedef struct opkg_intercept *opkg_intercept_t; -opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf) +static opkg_intercept_t +opkg_prep_intercepts(void) { opkg_intercept_t ctx; char *newpath; - int gen; - - ctx = malloc (sizeof (*ctx)); - ctx->oldpath = strdup (getenv ("PATH")); - - sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath); - setenv ("PATH", newpath, 1); - free (newpath); - - gen = 0; - retry: - sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen); - if (mkdir (ctx->statedir, 0770) < 0) { - if (errno == EEXIST) { - free (ctx->statedir); - gen++; - goto retry; - } - perror (ctx->statedir); + + ctx = xcalloc(1, sizeof (*ctx)); + ctx->oldpath = xstrdup(getenv("PATH")); + sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath); + sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX", conf->tmp_dir); + + if (mkdtemp(ctx->statedir) == NULL) { + opkg_perror(ERROR,"Failed to make temp dir %s", ctx->statedir); + free(ctx->oldpath); + free(ctx->statedir); + free(newpath); + free(ctx); return NULL; } - setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1); + + setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1); + setenv("PATH", newpath, 1); + free(newpath); + return ctx; } -int opkg_finalize_intercepts(opkg_intercept_t ctx) +static int +opkg_finalize_intercepts(opkg_intercept_t ctx) { - char *cmd; DIR *dir; int err = 0; @@ -417,97 +269,196 @@ int opkg_finalize_intercepts(opkg_intercept_t ctx) struct dirent *de; while (de = readdir (dir), de != NULL) { char *path; - + if (de->d_name[0] == '.') continue; - + sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name); if (access (path, X_OK) == 0) { - if (system (path)) { - err = errno; - perror (de->d_name); - } + const char *argv[] = {"sh", "-c", path, NULL}; + xsystem (argv); } free (path); } + closedir(dir); } else - perror (ctx->statedir); - - sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir); - system (cmd); - free (cmd); + opkg_perror(ERROR, "Failed to open dir %s", ctx->statedir); + rm_r(ctx->statedir); free (ctx->statedir); free (ctx); return err; } -int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name) +/* For package pkg do the following: If it is already visited, return. If not, + add it in visited list and recurse to its deps. Finally, add it to ordered + list. + pkg_vec all contains all available packages in repos. + pkg_vec visited contains packages already visited by this function, and is + used to end recursion and avoid an infinite loop on graph cycles. + pkg_vec ordered will finally contain the ordered set of packages. +*/ +static int +opkg_recurse_pkgs_in_order(pkg_t *pkg, pkg_vec_t *all, + pkg_vec_t *visited, pkg_vec_t *ordered) { - pkg_vec_t *all; + int j,k,l,m; + int count; + pkg_t *dep; + compound_depend_t * compound_depend; + depend_t ** possible_satisfiers; + abstract_pkg_t *abpkg; + abstract_pkg_t **dependents; + + /* If it's just an available package, that is, not installed and not even + unpacked, skip it */ + /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED + would do here. However, if there is an intermediate node (pkg) that is + configured and installed between two unpacked packages, the latter + won't be properly reordered, unless all installed/unpacked pkgs are + checked */ + if (pkg->state_status == SS_NOT_INSTALLED) + return 0; + + /* If the package has already been visited (by this function), skip it */ + for(j = 0; j < visited->len; j++) + if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) { + opkg_msg(DEBUG, "pkg %s already visited, skipping.\n", pkg->name); + return 0; + } + + pkg_vec_insert(visited, pkg); + + count = pkg->pre_depends_count + pkg->depends_count + \ + pkg->recommends_count + pkg->suggests_count; + + opkg_msg(DEBUG, "pkg %s.\n", pkg->name); + + /* Iterate over all the dependencies of pkg. For each one, find a package + that is either installed or unpacked and satisfies this dependency. + (there should only be one such package per dependency installed or + unpacked). Then recurse to the dependency package */ + for (j=0; j < count ; j++) { + compound_depend = &pkg->depends[j]; + possible_satisfiers = compound_depend->possibilities; + for (k=0; k < compound_depend->possibility_count ; k++) { + abpkg = possible_satisfiers[k]->pkg; + dependents = abpkg->provided_by->pkgs; + l = 0; + if (dependents != NULL) + while (l < abpkg->provided_by->len && dependents[l] != NULL) { + opkg_msg(DEBUG, "Descending on pkg %s.\n", + dependents [l]->name); + + /* find whether dependent l is installed or unpacked, + * and then find which package in the list satisfies it */ + for(m = 0; m < all->len; m++) { + dep = all->pkgs[m]; + if ( dep->state_status != SS_NOT_INSTALLED) + if ( ! strcmp(dep->name, dependents[l]->name)) { + opkg_recurse_pkgs_in_order(dep, all, + visited, ordered); + /* Stop the outer loop */ + l = abpkg->provided_by->len; + /* break from the inner loop */ + break; + } + } + l++; + } + } + } + + /* When all recursions from this node down, are over, and all + dependencies have been added in proper order in the ordered array, add + also the package pkg to ordered array */ + pkg_vec_insert(ordered, pkg); + + return 0; + +} + +static int +opkg_configure_packages(char *pkg_name) +{ + pkg_vec_t *all, *ordered, *visited; int i; pkg_t *pkg; opkg_intercept_t ic; int r, err = 0; - opkg_message(conf, OPKG_INFO, - "Configuring unpacked packages\n"); - fflush( stdout ); + opkg_msg(INFO, "Configuring unpacked packages.\n"); all = pkg_vec_alloc(); - pkg_hash_fetch_available(&conf->pkg_hash, all); - ic = opkg_prep_intercepts (conf); - + pkg_hash_fetch_available(all); + + /* Reorder pkgs in order to be configured according to the Depends: tag + order */ + opkg_msg(INFO, "Reordering packages before configuring them...\n"); + ordered = pkg_vec_alloc(); + visited = pkg_vec_alloc(); for(i = 0; i < all->len; i++) { - pkg = all->pkgs[i]; + pkg = all->pkgs[i]; + opkg_recurse_pkgs_in_order(pkg, all, visited, ordered); + } + + ic = opkg_prep_intercepts(); + if (ic == NULL) { + err = -1; + goto error; + } - if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) + for(i = 0; i < ordered->len; i++) { + pkg = ordered->pkgs[i]; + + if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) continue; if (pkg->state_status == SS_UNPACKED) { - opkg_message(conf, OPKG_NOTICE, - "Configuring %s\n", pkg->name); - fflush( stdout ); - r = opkg_configure(conf, pkg); + opkg_msg(NOTICE, "Configuring %s.\n", pkg->name); + r = opkg_configure(pkg); if (r == 0) { pkg->state_status = SS_INSTALLED; pkg->parent->state_status = SS_INSTALLED; pkg->state_flag &= ~SF_PREFER; + opkg_state_changed++; } else { - if (!err) - err = r; + err = -1; } } } - r = opkg_finalize_intercepts (ic); - if (r && !err) - err = r; + if (opkg_finalize_intercepts (ic)) + err = -1; +error: pkg_vec_free(all); + pkg_vec_free(ordered); + pkg_vec_free(visited); + return err; } -static opkg_conf_t *global_conf; +static int +opkg_remove_cmd(int argc, char **argv); -static void sigint_handler(int sig) -{ - signal(sig, SIG_DFL); - opkg_message(NULL, OPKG_NOTICE, - "opkg: interrupted. writing out status database\n"); - write_status_files_if_changed(global_conf); - exit(128 + sig); -} - -static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_install_cmd(int argc, char **argv) { int i; char *arg; - int err=0; + int err = 0; + + if (conf->force_reinstall) { + int saved_force_depends = conf->force_depends; + conf->force_depends = 1; + (void)opkg_remove_cmd(argc, argv); + conf->force_depends = saved_force_depends; + conf->force_reinstall = 0; + } - global_conf = conf; signal(SIGINT, sigint_handler); /* @@ -516,604 +467,426 @@ static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv) for (i=0; i < argc; i++) { arg = argv[i]; - opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg ); - err = opkg_prepare_url_for_install(conf, arg, &argv[i]); - if (err != EINVAL && err != 0) - return err; + opkg_msg(DEBUG2, "%s\n", arg); + if (opkg_prepare_url_for_install(arg, &argv[i])) + return -1; } - pkg_info_preinstall_check(conf); + pkg_info_preinstall_check(); for (i=0; i < argc; i++) { arg = argv[i]; - if (conf->multiple_providers) - err = opkg_install_multi_by_name(conf, arg); - else{ - err = opkg_install_by_name(conf, arg); - } - if (err == OPKG_PKG_HAS_NO_CANDIDATE) { - opkg_message(conf, OPKG_ERROR, - "Cannot find package %s.\n" - "Check the spelling or perhaps run 'opkg update'\n", - arg); + if (opkg_install_by_name(arg)) { + opkg_msg(ERROR, "Cannot install package %s.\n", arg); + err = -1; } } - /* recheck to verify that all dependences are satisfied */ - if (0) opkg_satisfy_all_dependences(conf); + if (opkg_configure_packages(NULL)) + err = -1; - opkg_configure_packages(conf, NULL); - - write_status_files_if_changed(conf); + write_status_files_if_changed(); return err; } -static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_upgrade_cmd(int argc, char **argv) { int i; pkg_t *pkg; - int err; + int err = 0; - global_conf = conf; signal(SIGINT, sigint_handler); if (argc) { for (i=0; i < argc; i++) { char *arg = argv[i]; - err = opkg_prepare_url_for_install(conf, arg, &arg); - if (err != EINVAL && err != 0) - return err; + if (opkg_prepare_url_for_install(arg, &arg)) + return -1; } - pkg_info_preinstall_check(conf); + pkg_info_preinstall_check(); for (i=0; i < argc; i++) { char *arg = argv[i]; if (conf->restrict_to_default_dest) { - pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash, - argv[i], - conf->default_dest); + pkg = pkg_hash_fetch_installed_by_name_dest(argv[i], + conf->default_dest); if (pkg == NULL) { - opkg_message(conf, OPKG_NOTICE, - "Package %s not installed in %s\n", + opkg_msg(NOTICE, "Package %s not installed in %s.\n", argv[i], conf->default_dest->name); continue; } } else { - pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, - argv[i]); + pkg = pkg_hash_fetch_installed_by_name(argv[i]); } - if (pkg) - opkg_upgrade_pkg(conf, pkg); - else { - opkg_install_by_name(conf, arg); + if (pkg) { + if (opkg_upgrade_pkg(pkg)) + err = -1; + } else { + if (opkg_install_by_name(arg)) + err = -1; } } - } else { - pkg_vec_t *installed = pkg_vec_alloc(); - - pkg_info_preinstall_check(conf); - - pkg_hash_fetch_all_installed(&conf->pkg_hash, installed); - for (i = 0; i < installed->len; i++) { - pkg = installed->pkgs[i]; - opkg_upgrade_pkg(conf, pkg); - } - pkg_vec_free(installed); } - /* recheck to verify that all dependences are satisfied */ - if (0) opkg_satisfy_all_dependences(conf); - - opkg_configure_packages(conf, NULL); + if (opkg_configure_packages(NULL)) + err = -1; - write_status_files_if_changed(conf); + write_status_files_if_changed(); - return 0; + return err; } -static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_download_cmd(int argc, char **argv) { - int i, err; + int i, err = 0; char *arg; pkg_t *pkg; - pkg_info_preinstall_check(conf); + pkg_info_preinstall_check(); for (i = 0; i < argc; i++) { arg = argv[i]; - pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg); + pkg = pkg_hash_fetch_best_installation_candidate_by_name(arg); if (pkg == NULL) { - opkg_message(conf, OPKG_ERROR, - "Cannot find package %s.\n" - "Check the spelling or perhaps run 'opkg update'\n", - arg); + opkg_msg(ERROR, "Cannot find package %s.\n", arg); continue; } - err = opkg_download_pkg(conf, pkg, "."); + if (opkg_download_pkg(pkg, ".")) + err = -1; if (err) { - opkg_message(conf, OPKG_ERROR, - "Failed to download %s\n", pkg->name); + opkg_msg(ERROR, "Failed to download %s.\n", pkg->name); } else { - opkg_message(conf, OPKG_NOTICE, - "Downloaded %s as %s\n", + opkg_msg(NOTICE, "Downloaded %s as %s.\n", pkg->name, pkg->local_filename); } } - return 0; + return err; } -static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_list_find_cmd(int argc, char **argv, int use_desc) { - int i ; + int i; pkg_vec_t *available; pkg_t *pkg; - char desc_short[OPKG_LIST_DESCRIPTION_LENGTH]; - char *newline; char *pkg_name = NULL; - char *version_str; if (argc > 0) { pkg_name = argv[0]; } available = pkg_vec_alloc(); - pkg_hash_fetch_available(&conf->pkg_hash, available); + pkg_hash_fetch_available(available); + pkg_vec_sort(available, pkg_compare_names); for (i=0; i < available->len; i++) { pkg = available->pkgs[i]; /* if we have package name or pattern and pkg does not match, then skip it */ - if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) + if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase) && + (!use_desc || !pkg->description || fnmatch(pkg_name, pkg->description, conf->nocase))) continue; - if (pkg->description) { - strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH); - } else { - desc_short[0] = '\0'; - } - desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0'; - newline = strchr(desc_short, '\n'); - if (newline) { - *newline = '\0'; - } -#ifndef OPKG_LIB - printf("%s - %s\n", pkg->name, desc_short); -#else - if (opkg_cb_list) { - version_str = pkg_version_str_alloc(pkg); - opkg_cb_list(pkg->name,desc_short, - version_str, - pkg->state_status, - p_userdata); - free(version_str); - } -#endif + print_pkg(pkg); } pkg_vec_free(available); return 0; } +static int +opkg_list_cmd(int argc, char **argv) +{ + return opkg_list_find_cmd(argc, argv, 0); +} -static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_find_cmd(int argc, char **argv) +{ + return opkg_list_find_cmd(argc, argv, 1); +} + + +static int +opkg_list_installed_cmd(int argc, char **argv) { int i ; pkg_vec_t *available; pkg_t *pkg; - char desc_short[OPKG_LIST_DESCRIPTION_LENGTH]; - char *newline; char *pkg_name = NULL; - char *version_str; if (argc > 0) { pkg_name = argv[0]; } available = pkg_vec_alloc(); - pkg_hash_fetch_all_installed(&conf->pkg_hash, available); + pkg_hash_fetch_all_installed(available); + pkg_vec_sort(available, pkg_compare_names); for (i=0; i < available->len; i++) { pkg = available->pkgs[i]; /* if we have package name or pattern and pkg does not match, then skip it */ - if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) + if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) continue; - if (pkg->description) { - strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH); - } else { - desc_short[0] = '\0'; - } - desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0'; - newline = strchr(desc_short, '\n'); - if (newline) { - *newline = '\0'; - } -#ifndef OPKG_LIB - printf("%s - %s\n", pkg->name, desc_short); -#else - if (opkg_cb_list) { - version_str = pkg_version_str_alloc(pkg); - opkg_cb_list(pkg->name,desc_short, - version_str, - pkg->state_status, - p_userdata); - free(version_str); - } -#endif + print_pkg(pkg); } + pkg_vec_free(available); + return 0; } -static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only) +static int +opkg_list_changed_conffiles_cmd(int argc, char **argv) { - int i; + int i ; pkg_vec_t *available; pkg_t *pkg; char *pkg_name = NULL; - char **pkg_fields = NULL; - int n_fields = 0; - char *buff ; // = (char *)malloc(1); + conffile_list_elt_t *iter; + conffile_t *cf; if (argc > 0) { pkg_name = argv[0]; } - if (argc > 1) { - pkg_fields = &argv[1]; - n_fields = argc - 1; + available = pkg_vec_alloc(); + pkg_hash_fetch_all_installed(available); + pkg_vec_sort(available, pkg_compare_names); + for (i=0; i < available->len; i++) { + pkg = available->pkgs[i]; + /* if we have package name or pattern and pkg does not match, then skip it */ + if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) + continue; + if (nv_pair_list_empty(&pkg->conffiles)) + continue; + for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) { + cf = (conffile_t *)iter->data; + if (cf->name && cf->value && conffile_has_been_modified(cf)) + printf("%s\n", cf->name); + } + } + pkg_vec_free(available); + return 0; +} + +static int +opkg_list_upgradable_cmd(int argc, char **argv) +{ + struct active_list *head = prepare_upgrade_list(); + struct active_list *node=NULL; + pkg_t *_old_pkg, *_new_pkg; + char *old_v, *new_v; + for (node = active_list_next(head, head); node;node = active_list_next(head,node)) { + _old_pkg = list_entry(node, pkg_t, list); + _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg->name); + if (_new_pkg == NULL) + continue; + old_v = pkg_version_str_alloc(_old_pkg); + new_v = pkg_version_str_alloc(_new_pkg); + printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v); + free(old_v); + free(new_v); + } + active_list_head_delete(head); + return 0; +} + +static int +opkg_info_status_cmd(int argc, char **argv, int installed_only) +{ + int i; + pkg_vec_t *available; + pkg_t *pkg; + char *pkg_name = NULL; + + if (argc > 0) { + pkg_name = argv[0]; } available = pkg_vec_alloc(); if (installed_only) - pkg_hash_fetch_all_installed(&conf->pkg_hash, available); + pkg_hash_fetch_all_installed(available); else - pkg_hash_fetch_available(&conf->pkg_hash, available); + pkg_hash_fetch_available(available); + for (i=0; i < available->len; i++) { pkg = available->pkgs[i]; - if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) { + if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) { continue; } -#ifndef OPKG_LIB - if (n_fields) { - for (j = 0; j < n_fields; j++) - pkg_print_field(pkg, stdout, pkg_fields[j]); - } else { - pkg_print_info(pkg, stdout); - } -#else - buff = pkg_formatted_info(pkg); - if ( buff ) { - if (opkg_cb_status) opkg_cb_status(pkg->name, - pkg->state_status, - buff, - p_userdata); -/* - We should not forget that actually the pointer is allocated. - We need to free it :) ( Thanks florian for seeing the error ) -*/ - free(buff); - } -#endif - if (conf->verbosity > 1) { + pkg_formatted_info(stdout, pkg); + + if (conf->verbosity >= NOTICE) { conffile_list_elt_t *iter; - for (iter = pkg->conffiles.head; iter; iter = iter->next) { - conffile_t *cf = iter->data; - int modified = conffile_has_been_modified(conf, cf); - opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n", + for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) { + conffile_t *cf = (conffile_t *)iter->data; + int modified = conffile_has_been_modified(cf); + if (cf->value) + opkg_msg(INFO, "conffile=%s md5sum=%s modified=%d.\n", cf->name, cf->value, modified); } } } -#ifndef OPKG_LIB - if (buff) - free(buff); -#endif pkg_vec_free(available); return 0; } -static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_info_cmd(int argc, char **argv) { - return opkg_info_status_cmd(conf, argc, argv, 0); + return opkg_info_status_cmd(argc, argv, 0); } -static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_status_cmd(int argc, char **argv) { - return opkg_info_status_cmd(conf, argc, argv, 1); + return opkg_info_status_cmd(argc, argv, 1); } -static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_configure_cmd(int argc, char **argv) { - - int err; - if (argc > 0) { - char *pkg_name = NULL; + int err; + char *pkg_name = NULL; - pkg_name = argv[0]; + if (argc > 0) + pkg_name = argv[0]; - err = opkg_configure_packages (conf, pkg_name); - - } else { - err = opkg_configure_packages (conf, NULL); - } + err = opkg_configure_packages(pkg_name); - write_status_files_if_changed(conf); + write_status_files_if_changed(); - return err; + return err; } -static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_remove_cmd(int argc, char **argv) { - int i, err; - char *globpattern; - glob_t globbuf; - - sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir); - err = glob(globpattern, 0, NULL, &globbuf); - free(globpattern); - if (err) { - return 0; - } - - opkg_message(conf, OPKG_NOTICE, - "The following packages in %s will now be installed.\n", - conf->pending_dir); - for (i = 0; i < globbuf.gl_pathc; i++) { - opkg_message(conf, OPKG_NOTICE, - "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]); - } - opkg_message(conf, OPKG_NOTICE, "\n"); - for (i = 0; i < globbuf.gl_pathc; i++) { - err = opkg_install_from_file(conf, globbuf.gl_pathv[i]); - if (err == 0) { - err = unlink(globbuf.gl_pathv[i]); - if (err) { - opkg_message(conf, OPKG_ERROR, - "%s: ERROR: failed to unlink %s: %s\n", - __FUNCTION__, globbuf.gl_pathv[i], strerror(err)); - return err; - } - } - } - globfree(&globbuf); - - return err; -} - -static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv) -{ - int i,a,done; + int i, a, done, err = 0; pkg_t *pkg; pkg_t *pkg_to_remove; pkg_vec_t *available; - char *pkg_name = NULL; - global_conf = conf; - signal(SIGINT, sigint_handler); -// ENH: Add the "no pkg removed" just in case. + done = 0; + + signal(SIGINT, sigint_handler); - done = 0; + pkg_info_preinstall_check(); available = pkg_vec_alloc(); - pkg_info_preinstall_check(conf); - if ( argc > 0 ) { - pkg_hash_fetch_all_installed(&conf->pkg_hash, available); - for (i=0; i < argc; i++) { - pkg_name = malloc(strlen(argv[i])+2); - strcpy(pkg_name,argv[i]); - for (a=0; a < available->len; a++) { - pkg = available->pkgs[a]; - if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) { - continue; - } - if (conf->restrict_to_default_dest) { - pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash, - pkg->name, - conf->default_dest); - } else { - pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name ); - } - - if (pkg == NULL) { - opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name); - continue; - } - if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped - opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name); - continue; - } - opkg_remove_pkg(conf, pkg_to_remove,0); - done = 1; - } - free (pkg_name); + pkg_hash_fetch_all_installed(available); + + for (i=0; ilen; a++) { + pkg = available->pkgs[a]; + if (fnmatch(argv[i], pkg->name, conf->nocase)) { + continue; + } + if (conf->restrict_to_default_dest) { + pkg_to_remove = pkg_hash_fetch_installed_by_name_dest( + pkg->name, + conf->default_dest); + } else { + pkg_to_remove = pkg_hash_fetch_installed_by_name(pkg->name); + } + + if (pkg_to_remove == NULL) { + opkg_msg(ERROR, "Package %s is not installed.\n", pkg->name); + continue; + } + if (pkg->state_status == SS_NOT_INSTALLED) { + opkg_msg(ERROR, "Package %s not installed.\n", pkg->name); + continue; + } + + if (opkg_remove_pkg(pkg_to_remove, 0)) + err = -1; + else + done = 1; } - pkg_vec_free(available); - } else { - pkg_vec_t *installed_pkgs = pkg_vec_alloc(); - int i; - int flagged_pkg_count = 0; - int removed; - - pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs); - - for (i = 0; i < installed_pkgs->len; i++) { - pkg_t *pkg = installed_pkgs->pkgs[i]; - if (pkg->state_flag & SF_USER) { - flagged_pkg_count++; - } else { - if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) - opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name); - } - } - if (!flagged_pkg_count) { - opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n" - "so refusing to uninstall unflagged non-leaf packages\n"); - return 0; - } - - /* find packages not flagged SF_USER (i.e., installed to - * satisfy a dependence) and not having any dependents, and - * remove them */ - do { - removed = 0; - for (i = 0; i < installed_pkgs->len; i++) { - pkg_t *pkg = installed_pkgs->pkgs[i]; - if (!(pkg->state_flag & SF_USER) - && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) { - removed++; - opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n"); - opkg_remove_pkg(conf, pkg,0); - done = 1; - } - } - } while (removed); - pkg_vec_free(installed_pkgs); } - if ( done == 0 ) - opkg_message(conf, OPKG_NOTICE, "No packages removed.\n"); - - write_status_files_if_changed(conf); - return 0; -} - -static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv) -{ - int i; - pkg_t *pkg; - - global_conf = conf; - signal(SIGINT, sigint_handler); - - pkg_info_preinstall_check(conf); - - for (i=0; i < argc; i++) { - if (conf->restrict_to_default_dest) { - pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash, - argv[i], - conf->default_dest); - } else { - pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]); - } + pkg_vec_free(available); - if (pkg == NULL) { - opkg_message(conf, OPKG_ERROR, - "Package %s is not installed.\n", argv[i]); - continue; - } - opkg_purge_pkg(conf, pkg); - } + if (done == 0) + opkg_msg(NOTICE, "No packages removed.\n"); - write_status_files_if_changed(conf); - return 0; + write_status_files_if_changed(); + return err; } -static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_flag_cmd(int argc, char **argv) { int i; pkg_t *pkg; const char *flags = argv[0]; - - global_conf = conf; + signal(SIGINT, sigint_handler); for (i=1; i < argc; i++) { if (conf->restrict_to_default_dest) { - pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash, - argv[i], + pkg = pkg_hash_fetch_installed_by_name_dest(argv[i], conf->default_dest); } else { - pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]); + pkg = pkg_hash_fetch_installed_by_name(argv[i]); } if (pkg == NULL) { - opkg_message(conf, OPKG_ERROR, - "Package %s is not installed.\n", argv[i]); + opkg_msg(ERROR, "Package %s is not installed.\n", argv[i]); continue; } if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)|| ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) { pkg->state_flag = pkg_state_flag_from_str(flags); } -/* pb_ asked this feature 03292004 */ -/* Actually I will use only this two, but this is an open for various status */ + + /* + * Useful if a package is installed in an offline_root, and + * should be configured by opkg-cl configure at a later date. + */ if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){ pkg->state_status = pkg_state_status_from_str(flags); } + opkg_state_changed++; - opkg_message(conf, OPKG_NOTICE, - "Setting flags for package %s to %s\n", + opkg_msg(NOTICE, "Setting flags for package %s to %s.\n", pkg->name, flags); } - write_status_files_if_changed(conf); + write_status_files_if_changed(); return 0; } -static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_files_cmd(int argc, char **argv) { pkg_t *pkg; - str_list_t *installed_files; + str_list_t *files; str_list_elt_t *iter; char *pkg_version; - size_t buff_len = 8192; - size_t used_len; - char *buff ; - - buff = (char *)malloc(buff_len); - if ( buff == NULL ) { - fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__); - return ENOMEM; - } - + if (argc < 1) { - return EINVAL; + return -1; } - pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, - argv[0]); + pkg = pkg_hash_fetch_installed_by_name(argv[0]); if (pkg == NULL) { - opkg_message(conf, OPKG_ERROR, - "Package %s not installed.\n", argv[0]); + opkg_msg(ERROR, "Package %s not installed.\n", argv[0]); return 0; } - installed_files = pkg_get_installed_files(pkg); + files = pkg_get_installed_files(pkg); pkg_version = pkg_version_str_alloc(pkg); -#ifndef OPKG_LIB printf("Package %s (%s) is installed on %s and has the following files:\n", - pkg->name, pkg_version, pkg->dest->name); - for (iter = installed_files->head; iter; iter = iter->next) { - puts(iter->data); - } -#else - if (buff) { - try_again: - used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n", - pkg->name, pkg_version, pkg->dest->name) + 1; - if (used_len > buff_len) { - buff_len *= 2; - buff = realloc (buff, buff_len); - goto try_again; - } - for (iter = installed_files->head; iter; iter = iter->next) { - used_len += strlen (iter->data) + 1; - while (buff_len <= used_len) { - buff_len *= 2; - buff = realloc (buff, buff_len); - } - strncat(buff, iter->data, buff_len); - strncat(buff, "\n", buff_len); - } - if (opkg_cb_list) opkg_cb_list(pkg->name, - buff, - pkg_version_str_alloc(pkg), - pkg->state_status, - p_userdata); - free(buff); - } -#endif + pkg->name, pkg_version, pkg->dest->name); + + for (iter=str_list_first(files); iter; iter=str_list_next(files, iter)) + printf("%s\n", (char *)iter->data); free(pkg_version); pkg_free_installed_files(pkg); @@ -1121,63 +894,65 @@ static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv) return 0; } -static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_depends_cmd(int argc, char **argv) { + int i, j, k; + int depends_count; + pkg_vec_t *available_pkgs; + compound_depend_t *cdep; + pkg_t *pkg; + char *str; - if (argc > 0) { - pkg_vec_t *available_pkgs = pkg_vec_alloc(); - const char *rel_str = "depends on"; - int i; - - pkg_info_preinstall_check(conf); + pkg_info_preinstall_check(); - if (conf->query_all) - pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs); - else - pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs); - for (i = 0; i < argc; i++) { - const char *target = argv[i]; - int j; + available_pkgs = pkg_vec_alloc(); + if (conf->query_all) + pkg_hash_fetch_available(available_pkgs); + else + pkg_hash_fetch_all_installed(available_pkgs); - opkg_message(conf, OPKG_ERROR, "target=%s\n", target); + for (i=0; ilen; j++) { + pkg = available_pkgs->pkgs[j]; + + if (fnmatch(argv[i], pkg->name, conf->nocase) != 0) + continue; + + depends_count = pkg->depends_count + + pkg->pre_depends_count + + pkg->recommends_count + + pkg->suggests_count; + + opkg_msg(NOTICE, "%s depends on:\n", pkg->name); + + for (k=0; kdepends[k]; + + if (cdep->type != DEPEND) + continue; + + str = pkg_depend_str(pkg, k); + opkg_msg(NOTICE, "\t%s\n", str); + free(str); + } - for (j = 0; j < available_pkgs->len; j++) { - pkg_t *pkg = available_pkgs->pkgs[j]; - if (fnmatch(target, pkg->name, 0) == 0) { - int k; - int count = pkg->depends_count + pkg->pre_depends_count; - opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n", - target, pkg->architecture, rel_str); - for (k = 0; k < count; k++) { - compound_depend_t *cdepend = &pkg->depends[k]; - int l; - for (l = 0; l < cdepend->possibility_count; l++) { - depend_t *possibility = cdepend->possibilities[l]; - opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name); - if (conf->verbosity > 0) { - // char *ver = abstract_pkg_version_str_alloc(possibility->pkg); - opkg_message(conf, OPKG_NOTICE, " %s", possibility->version); - if (possibility->version) { - char *typestr = NULL; - switch (possibility->constraint) { - case NONE: typestr = "none"; break; - case EARLIER: typestr = "<"; break; - case EARLIER_EQUAL: typestr = "<="; break; - case EQUAL: typestr = "="; break; - case LATER_EQUAL: typestr = ">="; break; - case LATER: typestr = ">"; break; - } - opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version); - } - // free(ver); - } - opkg_message(conf, OPKG_ERROR, "\n"); - } - } - } } - } - pkg_vec_free(available_pkgs); + } + + pkg_vec_free(available_pkgs); + return 0; +} + +static int +pkg_mark_provides(pkg_t *pkg) +{ + int provides_count = pkg->provides_count; + abstract_pkg_t **provides = pkg->provides; + int i; + pkg->parent->state_flag |= SF_MARKED; + for (i = 0; i < provides_count; i++) { + provides[i]->state_flag |= SF_MARKED; } return 0; } @@ -1191,178 +966,183 @@ enum what_field_type { WHATSUGGESTS }; -static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv) +static int +opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive, int argc, char **argv) { + depend_t *possibility; + compound_depend_t *cdep; + pkg_vec_t *available_pkgs; + pkg_t *pkg; + int i, j, k, l; + int changed, count; + const char *rel_str = NULL; + char *ver; + + switch (what_field_type) { + case DEPEND: rel_str = "depends on"; break; + case CONFLICTS: rel_str = "conflicts with"; break; + case SUGGEST: rel_str = "suggests"; break; + case RECOMMEND: rel_str = "recommends"; break; + default: return -1; + } - if (argc > 0) { - pkg_vec_t *available_pkgs = pkg_vec_alloc(); - const char *rel_str = NULL; - int i; - int changed; - - switch (what_field_type) { - case WHATDEPENDS: rel_str = "depends on"; break; - case WHATCONFLICTS: rel_str = "conflicts with"; break; - case WHATSUGGESTS: rel_str = "suggests"; break; - case WHATRECOMMENDS: rel_str = "recommends"; break; - case WHATPROVIDES: rel_str = "provides"; break; - case WHATREPLACES: rel_str = "replaces"; break; - } - - if (conf->query_all) - pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs); - else - pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs); + available_pkgs = pkg_vec_alloc(); - /* mark the root set */ - pkg_vec_clear_marks(available_pkgs); - opkg_message(conf, OPKG_NOTICE, "Root set:\n"); - for (i = 0; i < argc; i++) { - const char *dependee_pattern = argv[i]; - pkg_vec_mark_if_matches(available_pkgs, dependee_pattern); - } - for (i = 0; i < available_pkgs->len; i++) { - pkg_t *pkg = available_pkgs->pkgs[i]; + if (conf->query_all) + pkg_hash_fetch_available(available_pkgs); + else + pkg_hash_fetch_all_installed(available_pkgs); + + /* mark the root set */ + pkg_vec_clear_marks(available_pkgs); + opkg_msg(NOTICE, "Root set:\n"); + for (i = 0; i < argc; i++) + pkg_vec_mark_if_matches(available_pkgs, argv[i]); + + for (i = 0; i < available_pkgs->len; i++) { + pkg = available_pkgs->pkgs[i]; if (pkg->state_flag & SF_MARKED) { /* mark the parent (abstract) package */ pkg_mark_provides(pkg); - opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name); + opkg_msg(NOTICE, " %s\n", pkg->name); } - } + } - opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str); - do { - int j; - changed = 0; + opkg_msg(NOTICE, "What %s root set\n", rel_str); + do { + changed = 0; - for (j = 0; j < available_pkgs->len; j++) { - pkg_t *pkg = available_pkgs->pkgs[j]; - int k; - int count = ((what_field_type == WHATCONFLICTS) + for (j=0; jlen; j++) { + + pkg = available_pkgs->pkgs[j]; + count = ((what_field_type == CONFLICTS) ? pkg->conflicts_count - : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count); - /* skip this package if it is already marked */ - if (pkg->parent->state_flag & SF_MARKED) { - continue; - } - for (k = 0; k < count; k++) { - compound_depend_t *cdepend = - (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k]; - int l; - for (l = 0; l < cdepend->possibility_count; l++) { - depend_t *possibility = cdepend->possibilities[l]; - if (possibility->pkg->state_flag & SF_MARKED) { - /* mark the depending package so we won't visit it again */ - pkg->state_flag |= SF_MARKED; - pkg_mark_provides(pkg); - changed++; - - opkg_message(conf, OPKG_NOTICE, " %s", pkg->name); - if (conf->verbosity > 0) { - char *ver = pkg_version_str_alloc(pkg); - opkg_message(conf, OPKG_NOTICE, " %s", ver); - opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name); + : pkg->pre_depends_count + + pkg->depends_count + + pkg->recommends_count + + pkg->suggests_count); + + /* skip this package if it is already marked */ + if (pkg->parent->state_flag & SF_MARKED) + continue; + + for (k=0; kconflicts[k] + : &pkg->depends[k]; + + if (what_field_type != cdep->type) + continue; + + for (l=0; lpossibility_count; l++) { + possibility = cdep->possibilities[l]; + + if ((possibility->pkg->state_flag + & SF_MARKED) + != SF_MARKED) + continue; + + /* mark the depending package so we + * won't visit it again */ + pkg->state_flag |= SF_MARKED; + pkg_mark_provides(pkg); + changed++; + + ver = pkg_version_str_alloc(pkg); + opkg_msg(NOTICE, "\t%s %s\t%s %s", + pkg->name, + ver, + rel_str, + possibility->pkg->name); + free(ver); if (possibility->version) { - char *typestr = NULL; - switch (possibility->constraint) { - case NONE: typestr = "none"; break; - case EARLIER: typestr = "<"; break; - case EARLIER_EQUAL: typestr = "<="; break; - case EQUAL: typestr = "="; break; - case LATER_EQUAL: typestr = ">="; break; - case LATER: typestr = ">"; break; - } - opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version); + opkg_msg(NOTICE, " (%s%s)", + constraint_to_str(possibility->constraint), + possibility->version); } - free(ver); - if (!pkg_dependence_satisfiable(conf, possibility)) - opkg_message(conf, OPKG_NOTICE, " unsatisfiable"); - } - opkg_message(conf, OPKG_NOTICE, "\n"); - goto next_package; - } - } - } - next_package: - ; - } - } while (changed && recursive); - pkg_vec_free(available_pkgs); - } + if (!pkg_dependence_satisfiable(possibility)) + opkg_msg(NOTICE, + " unsatisfiable"); + opkg_message(NOTICE, "\n"); + goto next_package; + } + } +next_package: + ; + } + } while (changed && recursive); - return 0; -} + pkg_vec_free(available_pkgs); -int pkg_mark_provides(pkg_t *pkg) -{ - int provides_count = pkg->provides_count; - abstract_pkg_t **provides = pkg->provides; - int i; - pkg->parent->state_flag |= SF_MARKED; - for (i = 0; i < provides_count; i++) { - provides[i]->state_flag |= SF_MARKED; - } - return 0; + return 0; } -static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_whatdepends_recursively_cmd(int argc, char **argv) { - return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv); + return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv); } -static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv) + +static int +opkg_whatdepends_cmd(int argc, char **argv) { - return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv); + return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv); } -static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_whatsuggests_cmd(int argc, char **argv) { - return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv); + return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv); } -static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_whatrecommends_cmd(int argc, char **argv) { - return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv); + return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv); } -static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_whatconflicts_cmd(int argc, char **argv) { - return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv); + return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv); } -static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv) +static int +opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc, char **argv) { if (argc > 0) { pkg_vec_t *available_pkgs = pkg_vec_alloc(); const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces"); int i; - - pkg_info_preinstall_check(conf); + + pkg_info_preinstall_check(); if (conf->query_all) - pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs); + pkg_hash_fetch_available(available_pkgs); else - pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs); + pkg_hash_fetch_all_installed(available_pkgs); for (i = 0; i < argc; i++) { const char *target = argv[i]; int j; - opkg_message(conf, OPKG_ERROR, "What %s %s\n", + opkg_msg(NOTICE, "What %s %s\n", rel_str, target); for (j = 0; j < available_pkgs->len; j++) { pkg_t *pkg = available_pkgs->pkgs[j]; int k; int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count; for (k = 0; k < count; k++) { - abstract_pkg_t *apkg = - ((what_field_type == WHATPROVIDES) + abstract_pkg_t *apkg = + ((what_field_type == WHATPROVIDES) ? pkg->provides[k] : pkg->replaces[k]); - if (fnmatch(target, apkg->name, 0) == 0) { - opkg_message(conf, OPKG_ERROR, " %s", pkg->name); - if (strcmp(target, apkg->name) != 0) - opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name); - opkg_message(conf, OPKG_ERROR, "\n"); + if (fnmatch(target, apkg->name, conf->nocase) == 0) { + opkg_msg(NOTICE, " %s", pkg->name); + if ((conf->nocase ? strcasecmp(target, apkg->name) : strcmp(target, apkg->name)) != 0) + opkg_msg(NOTICE, "\t%s %s\n", + rel_str, apkg->name); + opkg_message(NOTICE, "\n"); } } } @@ -1372,17 +1152,20 @@ static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_ty return 0; } -static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_whatprovides_cmd(int argc, char **argv) { - return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv); + return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv); } -static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_whatreplaces_cmd(int argc, char **argv) { - return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv); + return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv); } -static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_search_cmd(int argc, char **argv) { int i; @@ -1393,75 +1176,118 @@ static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv) char *installed_file; if (argc < 1) { - return EINVAL; + return -1; } - + installed = pkg_vec_alloc(); - pkg_hash_fetch_all_installed(&conf->pkg_hash, installed); + pkg_hash_fetch_all_installed(installed); + pkg_vec_sort(installed, pkg_compare_names); for (i=0; i < installed->len; i++) { pkg = installed->pkgs[i]; installed_files = pkg_get_installed_files(pkg); - for (iter = installed_files->head; iter; iter = iter->next) { - installed_file = iter->data; - if (fnmatch(argv[0], installed_file, 0)==0) { -#ifndef OPKG_LIB - printf("%s: %s\n", pkg->name, installed_file); -#else - if (opkg_cb_list) opkg_cb_list(pkg->name, - installed_file, - pkg_version_str_alloc(pkg), - pkg->state_status, p_userdata); -#endif - } + for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) { + installed_file = (char *)iter->data; + if (fnmatch(argv[0], installed_file, conf->nocase)==0) + print_pkg(pkg); } pkg_free_installed_files(pkg); } - /* XXX: CLEANUP: It's not obvious from the name of - pkg_hash_fetch_all_installed that we need to call - pkg_vec_free to avoid a memory leak. */ pkg_vec_free(installed); return 0; } -static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_compare_versions_cmd(int argc, char **argv) { if (argc == 3) { /* this is a bit gross */ struct pkg p1, p2; - parseVersion(&p1, argv[0]); - parseVersion(&p2, argv[2]); + parse_version(&p1, argv[0]); + parse_version(&p2, argv[2]); return pkg_version_satisfied(&p1, &p2, argv[1]); } else { - opkg_message(conf, OPKG_ERROR, + opkg_msg(ERROR, "opkg compare_versions \n" " is one of <= >= << >> =\n"); return -1; } } -#ifndef HOST_CPU_STR -#define HOST_CPU_STR__(X) #X -#define HOST_CPU_STR_(X) HOST_CPU_STR__(X) -#define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO) -#endif - -static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv) +static int +opkg_print_architecture_cmd(int argc, char **argv) { nv_pair_list_elt_t *l; - l = conf->arch_list.head; - while (l) { - nv_pair_t *nv = l->data; + list_for_each_entry(l, &conf->arch_list.head, node) { + nv_pair_t *nv = (nv_pair_t *)l->data; printf("arch %s %s\n", nv->name, nv->value); - l = l->next; } return 0; } +/* XXX: CLEANUP: The usage strings should be incorporated into this + array for easier maintenance */ +static opkg_cmd_t cmds[] = { + {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"upgrade", 1, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd, PFM_SOURCE}, + {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE}, + {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE}, + {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE}, + {"list-upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE}, + {"list_changed_conffiles", 0, (opkg_cmd_fun_t)opkg_list_changed_conffiles_cmd, PFM_SOURCE}, + {"list-changed-conffiles", 0, (opkg_cmd_fun_t)opkg_list_changed_conffiles_cmd, PFM_SOURCE}, + {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd, 0}, + {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"find", 1, (opkg_cmd_fun_t)opkg_find_cmd, PFM_SOURCE}, + {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd, PFM_DESCRIPTION|PFM_SOURCE}, +}; + +opkg_cmd_t * +opkg_cmd_find(const char *name) +{ + int i; + opkg_cmd_t *cmd; + int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t); + + for (i=0; i < num_cmds; i++) { + cmd = &cmds[i]; + if (strcmp(name, cmd->name) == 0) + return cmd; + } + + return NULL; +} + +int +opkg_cmd_exec(opkg_cmd_t *cmd, int argc, const char **argv) +{ + return (cmd->fun)(argc, argv); +}