X-Git-Url: https://git.librecmc.org/?p=oweals%2Fopkg-lede.git;a=blobdiff_plain;f=libopkg%2Fopkg_cmd.c;h=2fe74e9d1394ea17b9a7394b6131651cbe301cec;hp=463b15d49f5081117c622ea57fad35e70bd4175a;hb=8c4195884fa30ef76e17835266745fb2c6d920f7;hpb=349953207b609b8019c348ba326671c07035846b diff --git a/libopkg/opkg_cmd.c b/libopkg/opkg_cmd.c index 463b15d..2fe74e9 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,17 +15,10 @@ General Public License for more details. */ -#include -#include "opkg.h" -#include -#include -#include -#include -#include -#include -#include +#include "includes.h" #include +#include #include "opkg_conf.h" #include "opkg_cmd.h" @@ -38,6 +31,8 @@ #include "file_util.h" #include "str_util.h" #include "libbb/libbb.h" +#include "opkg_utils.h" +#include "opkg_defines.h" #include @@ -77,6 +72,7 @@ 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); +static int pkg_mark_provides(pkg_t *pkg); /* XXX: CLEANUP: The usage strings should be incorporated into this array for easier maintenance */ @@ -121,7 +117,7 @@ static void write_status_files_if_changed(opkg_conf_t *conf) opkg_conf_write_status_files(conf); pkg_write_changed_filelists(conf); } else { - opkg_message(conf, OPKG_NOTICE, "Nothing to be done\n"); + opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n"); } } @@ -143,6 +139,23 @@ opkg_cmd_t *opkg_cmd_find(const char *name) return NULL; } +void opkg_print_error_list (opkg_conf_t *conf) +{ + if ( error_list ) { + reverse_error_list(&error_list); + + printf ("Collected errors:\n"); + /* Here we print the errors collected and free the list */ + while (error_list != NULL) { + printf (" * %s", error_list->errmsg); + error_list = error_list->next; + + } + free_error_list(&error_list); + } + +} + int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata) { int result; @@ -151,24 +164,12 @@ int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **arg result = (cmd->fun)(conf, argc, argv); - if ( result != 0 ) { + if ( result != 0 && !error_list) { 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; + opkg_print_error_list (conf); - } - free_error_list(&error_list); - - } - p_userdata = NULL; return result; } @@ -231,7 +232,7 @@ static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv) FILE *in, *out; sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name); - err = opkg_download(conf, url, tmp_file_name); + err = opkg_download(conf, url, tmp_file_name, NULL, NULL); if (err == 0) { opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url); in = fopen (tmp_file_name, "r"); @@ -247,7 +248,7 @@ static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv) unlink (tmp_file_name); } } else - err = opkg_download(conf, url, list_file_name); + err = opkg_download(conf, url, list_file_name, NULL, NULL); if (err) { failures++; } else { @@ -271,13 +272,13 @@ static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv) sprintf_alloc (&tmp_file_name, "%s/%s", tmp, "Packages.sig"); - err = opkg_download(conf, url, tmp_file_name); + err = opkg_download(conf, url, tmp_file_name, NULL, NULL); if (err) { failures++; opkg_message (conf, OPKG_NOTICE, "Signature check failed\n"); } else { int err; - err = opkg_verify_file (list_file_name, tmp_file_name); + err = opkg_verify_file (conf, list_file_name, tmp_file_name); if (err == 0) opkg_message (conf, OPKG_NOTICE, "Signature check passed\n"); else @@ -300,36 +301,6 @@ static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv) } -/* 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; @@ -338,14 +309,21 @@ 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(opkg_conf_t *conf) { opkg_intercept_t ctx; + char *oldpath; char *newpath; int gen; ctx = malloc (sizeof (*ctx)); - ctx->oldpath = strdup (getenv ("PATH")); + oldpath = getenv ("PATH"); + if (oldpath) { + ctx->oldpath = strdup (oldpath); + } else { + ctx->oldpath = 0; + } + sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath); setenv ("PATH", newpath, 1); @@ -367,14 +345,18 @@ opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf) 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; - setenv ("PATH", ctx->oldpath, 1); - free (ctx->oldpath); + if (ctx->oldpath) { + setenv ("PATH", ctx->oldpath, 1); + free (ctx->oldpath); + } else { + unsetenv("PATH"); + } dir = opendir (ctx->statedir); if (dir) { @@ -407,9 +389,99 @@ int opkg_finalize_intercepts(opkg_intercept_t 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(opkg_conf_t *conf, 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_message(conf, OPKG_INFO, + " pkg: %s already visited\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_message(conf, OPKG_INFO, + " 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 (dependents [l] != NULL && l < abpkg->provided_by->len) { + opkg_message(conf, OPKG_INFO, + " 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(conf, 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(opkg_conf_t *conf, char *pkg_name) +{ + pkg_vec_t *all, *ordered, *visited; int i; pkg_t *pkg; opkg_intercept_t ic; @@ -420,8 +492,21 @@ int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name) fflush( stdout ); all = pkg_vec_alloc(); + pkg_hash_fetch_available(&conf->pkg_hash, all); + /* Reorder pkgs in order to be configured according to the Depends: tag + order */ + opkg_message(conf, OPKG_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]; + opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered); + } + + ic = opkg_prep_intercepts (conf); for(i = 0; i < all->len; i++) { @@ -451,6 +536,9 @@ int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name) err = r; pkg_vec_free(all); + pkg_vec_free(ordered); + pkg_vec_free(visited); + return err; } @@ -489,15 +577,10 @@ static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv) 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); - } + 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", + "Cannot find package %s.\n", arg); } } @@ -586,7 +669,7 @@ static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv) 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(conf, arg, &err); if (pkg == NULL) { opkg_message(conf, OPKG_ERROR, "Cannot find package %s.\n" @@ -837,9 +920,9 @@ static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv) done = 0; - available = pkg_vec_alloc(); pkg_info_preinstall_check(conf); if ( argc > 0 ) { + available = pkg_vec_alloc(); pkg_hash_fetch_all_installed(&conf->pkg_hash, available); for (i=0; i < argc; i++) { pkg_name = malloc(strlen(argv[i])+2); @@ -1228,7 +1311,7 @@ static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_ty return 0; } -int pkg_mark_provides(pkg_t *pkg) +static int pkg_mark_provides(pkg_t *pkg) { int provides_count = pkg->provides_count; abstract_pkg_t **provides = pkg->provides;