diff --git a/bin/xbps-bin/defs.h b/bin/xbps-bin/defs.h index 37f9acb44d6..578ab688ffe 100644 --- a/bin/xbps-bin/defs.h +++ b/bin/xbps-bin/defs.h @@ -29,5 +29,6 @@ void xbps_install_pkg(const char *, bool, bool); void xbps_autoremove_pkgs(void); void xbps_remove_pkg(const char *, bool); +void xbps_autoupdate_pkgs(bool); #endif /* !_XBPS_BIN_DEFS_H_ */ diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c index 6d66f88ad1d..516ae968f6a 100644 --- a/bin/xbps-bin/install.c +++ b/bin/xbps-bin/install.c @@ -65,73 +65,48 @@ show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done) return EINVAL; } -void -xbps_install_pkg(const char *pkg, bool force, bool update) +static void +check_pkg_hashes(prop_dictionary_t props, prop_object_iterator_t iter) +{ + prop_object_t obj; + const char *repoloc, *filename; + int rv = 0; + + printf("Checking binary package file(s) integrity...\n"); + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); + prop_dictionary_get_cstring_nocopy(obj, "filename", &filename); + rv = xbps_check_pkg_file_hash(obj, repoloc); + if (rv != 0 && rv != ERANGE) { + printf("error: checking hash for %s (%s)\n", + filename, strerror(rv)); + prop_object_release(props); + exit(EXIT_FAILURE); + } else if (rv != 0 && rv == ERANGE) { + printf("Hash doesn't match for %s!\n", filename); + prop_object_release(props); + exit(EXIT_FAILURE); + } + } + prop_object_iterator_reset(iter); + printf("\n"); +} + +static void +show_transaction_sizes(prop_dictionary_t props, prop_object_iterator_t iter, + const char *descr) { - prop_dictionary_t props, instpkg; - prop_array_t array; prop_object_t obj; - prop_object_iterator_t iter; uint64_t tsize = 0, dlsize = 0, instsize = 0; size_t cols = 0; - const char *repoloc, *filename, *instver, *origin; const char *pkgname, *version; char size[64]; - int rv = 0; - bool pkg_is_dep, doup = false, first = false; - - assert(props != NULL); - - /* - * Find and sort all required package dictionaries. - */ - printf("Finding/sorting required binary packages...\n"); - - rv = xbps_prepare_pkg(pkg); - if (rv != 0 && rv == EAGAIN) { - printf("Unable to locate %s in repository pool.\n", pkg); - exit(EXIT_FAILURE); - } else if (rv != 0 && rv != ENOENT) { - printf("Unexpected error: %s\n", strerror(rv)); - exit(EXIT_FAILURE); - } - - props = xbps_get_pkg_props(pkg); - if (props == NULL) { - printf("error: unexistent props dictionary!\n"); - exit(EXIT_FAILURE); - } - - /* - * Bail out if there are unresolved deps. - */ - array = prop_dictionary_get(props, "missing_deps"); - if (prop_array_count(array) > 0) { - show_missing_deps(props, pkg); - prop_object_release(props); - exit(EXIT_FAILURE); - } - - prop_dictionary_get_cstring_nocopy(props, "origin", &origin); + bool first = false; /* * Iterate over the list of packages that are going to be * installed and check the file hash. */ - array = prop_dictionary_get(props, "packages"); - if (array == NULL || prop_array_count(array) == 0) { - printf("error: empty packages array!\n"); - prop_object_release(props); - exit(EXIT_FAILURE); - } - - iter = prop_array_iterator(array); - if (iter == NULL) { - printf("error: allocating array mem! (%s)\n", strerror(errno)); - prop_object_release(props); - exit(EXIT_FAILURE); - } - while ((obj = prop_object_iterator_next(iter)) != NULL) { prop_dictionary_get_uint64(obj, "filename-size", &tsize); dlsize += tsize; @@ -145,7 +120,7 @@ xbps_install_pkg(const char *pkg, bool force, bool update) /* * Show the list of packages that will be installed. */ - printf("\nThe following new packages will be installed:\n\n"); + printf("\nThe following new packages will be %s:\n\n", descr); while ((obj = prop_object_iterator_next(iter)) != NULL) { prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); @@ -182,7 +157,71 @@ xbps_install_pkg(const char *pkg, bool force, bool update) exit(EXIT_FAILURE); } printf("Total installed size: %s\n\n", size); +} +void +xbps_install_pkg(const char *pkg, bool force, bool update) +{ + prop_dictionary_t props, instpkg; + prop_array_t array; + prop_object_t obj; + prop_object_iterator_t iter; + const char *instver, *origin, *pkgname, *version; + int rv = 0; + bool pkg_is_dep, doup = false; + + /* + * Find and sort all required package dictionaries. + */ + printf("Finding/sorting required binary packages...\n"); + + rv = xbps_prepare_pkg(pkg); + if (rv != 0 && rv == EAGAIN) { + printf("Unable to locate %s in repository pool.\n", pkg); + exit(EXIT_FAILURE); + } else if (rv != 0 && rv != ENOENT) { + printf("Unexpected error: %s\n", strerror(rv)); + exit(EXIT_FAILURE); + } + + props = xbps_get_pkg_props(); + if (props == NULL) { + printf("error: unexistent props dictionary!\n"); + exit(EXIT_FAILURE); + } + + /* + * Bail out if there are unresolved deps. + */ + array = prop_dictionary_get(props, "missing_deps"); + if (prop_array_count(array) > 0) { + show_missing_deps(props, pkg); + prop_object_release(props); + exit(EXIT_FAILURE); + } + + prop_dictionary_get_cstring_nocopy(props, "origin", &origin); + + array = prop_dictionary_get(props, "packages"); + if (array == NULL || prop_array_count(array) == 0) { + printf("error: empty packages array!\n"); + prop_object_release(props); + exit(EXIT_FAILURE); + } + iter = prop_array_iterator(array); + if (iter == NULL) { + printf("error: allocating array mem! (%s)\n", strerror(errno)); + prop_object_release(props); + exit(EXIT_FAILURE); + } + /* + * Show download/installed size for the transaction. + */ + show_transaction_sizes(props, iter, "installed"); + + /* + * Ask interactively (if -f not set). + */ if (force == false) { if (xbps_noyes("Do you want to continue?") == false) { printf("Aborting!\n"); @@ -191,24 +230,10 @@ xbps_install_pkg(const char *pkg, bool force, bool update) } } - printf("Checking binary package file(s) integrity...\n"); - while ((obj = prop_object_iterator_next(iter)) != NULL) { - prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); - prop_dictionary_get_cstring_nocopy(obj, "filename", &filename); - rv = xbps_check_pkg_file_hash(obj, repoloc); - if (rv != 0 && rv != ERANGE) { - printf("error: checking hash for %s (%s)\n", - filename, strerror(rv)); - prop_object_release(props); - exit(EXIT_FAILURE); - } else if (rv != 0 && rv == ERANGE) { - printf("Hash doesn't match for %s!\n", filename); - prop_object_release(props); - exit(EXIT_FAILURE); - } - } - prop_object_iterator_reset(iter); - printf("\n"); + /* + * Check the SHA256 hash for all required packages. + */ + check_pkg_hashes(props, iter); /* * Install all packages, the list is already sorted. @@ -276,3 +301,144 @@ xbps_install_pkg(const char *pkg, bool force, bool update) exit(EXIT_SUCCESS); } + +void +xbps_autoupdate_pkgs(bool force) +{ + prop_dictionary_t dict, props, instpkg; + prop_array_t array; + prop_object_t obj; + prop_object_iterator_t iter; + const char *pkgname, *version, *instver; + int rv = 0; + + dict = xbps_get_regpkgdb_dict(); + if (dict == NULL) { + printf("No packages currently installed (%s).\n", + strerror(errno)); + exit(EXIT_SUCCESS); + } + + iter = xbps_get_array_iter_from_dict(dict, "packages"); + if (iter == NULL) { + xbps_release_regpkgdb_dict(); + exit(EXIT_FAILURE); + } + + if (xbps_prepare_repolist_data() != 0) { + prop_object_iterator_release(iter); + xbps_release_regpkgdb_dict(); + exit(EXIT_FAILURE); + } + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); + rv = xbps_find_new_pkg(pkgname, obj); + if (rv != 0) + break; + } + prop_object_iterator_release(iter); + xbps_release_regpkgdb_dict(); + + /* Sort the list of packages */ + props = xbps_get_pkg_props(); + if (props == NULL) { + if (errno == 0) { + printf("All packages are up-to-date.\n"); + exit(EXIT_SUCCESS); + } + printf("Error while checking for new pkgs: %s\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + if ((rv = xbps_sort_pkg_deps(props)) != 0) { + printf("Error while sorting packages: %s\n", + strerror(rv)); + exit(EXIT_FAILURE); + } + /* Update all packages now */ + array = prop_dictionary_get(props, "packages"); + if (array == NULL || prop_array_count(array) == 0) { + printf("error: empty packages array!\n"); + prop_object_release(props); + exit(EXIT_FAILURE); + } + iter = prop_array_iterator(array); + if (iter == NULL) { + printf("error: allocating array mem! (%s)\n", strerror(errno)); + prop_object_release(props); + exit(EXIT_FAILURE); + } + + /* + * Show download/installed size for the transaction. + */ + show_transaction_sizes(props, iter, "upgraded"); + + /* + * Ask interactively (if -f not set). + */ + if (force == false) { + if (xbps_noyes("Do you want to continue?") == false) { + printf("Aborting!\n"); + prop_object_release(props); + exit(EXIT_SUCCESS); + } + } + + /* + * Check the SHA256 hash for all required packages. + */ + check_pkg_hashes(props, iter); + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); + prop_dictionary_get_cstring_nocopy(obj, "version", &version); + + /* + * Update a package, firstly removing current package. + */ + instpkg = xbps_find_pkg_installed_from_plist(pkgname); + if (instpkg == NULL) { + printf("error: unable to find %s installed " + "dict!\n", pkgname); + prop_object_release(props); + exit(EXIT_FAILURE); + } + + prop_dictionary_get_cstring_nocopy(instpkg, + "version", &instver); + printf("Updating package %s-%s to %s...\n", pkgname, + instver, version); + prop_object_release(instpkg); + rv = xbps_remove_binary_pkg(pkgname, true); + if (rv != 0) { + printf("error: removing %s-%s (%s)\n", + pkgname, instver, strerror(rv)); + prop_object_release(props); + exit(EXIT_FAILURE); + } + + /* + * Unpack binary package. + */ + if ((rv = xbps_unpack_binary_pkg(obj)) != 0) { + printf("error: unpacking %s-%s (%s)\n", pkgname, + version, strerror(rv)); + prop_object_release(props); + exit(EXIT_FAILURE); + } + /* + * Register binary package. + */ + if ((rv = xbps_register_pkg(obj, true, false)) != 0) { + printf("error: registering %s-%s! (%s)\n", + pkgname, version, strerror(rv)); + prop_object_release(props); + exit(EXIT_FAILURE); + } + } + prop_object_iterator_release(iter); + xbps_release_repolist_data(); + exit(EXIT_SUCCESS); +} diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index 589156c7ed0..5b823484fb1 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -45,7 +45,8 @@ usage(void) { printf("Usage: xbps-bin [options] [target] [arguments]\n\n" " Available targets:\n" - " autoremove, files, install, list, remove, show, update\n" + " autoremove, autoupdate, files, install, list, remove\n" + " show, update\n" " Targets with arguments:\n" " files\t\n" " install\t\n" @@ -63,6 +64,7 @@ usage(void) "\n" " Examples:\n" " $ xbps-bin autoremove\n" + " $ xbps-bin autoupdate\n" " $ xbps-bin -C files klibc\n" " $ xbps-bin install klibc\n" " $ xbps-bin -r /path/to/root install klibc\n" @@ -204,6 +206,15 @@ main(int argc, char **argv) exit(EXIT_FAILURE); } + } else if (strcasecmp(argv[0], "autoupdate") == 0) { + /* + * To update all packages currently installed. + */ + if (argc != 1) + usage(); + + xbps_autoupdate_pkgs(force); + } else if (strcasecmp(argv[0], "autoremove") == 0) { /* * Removes orphan pkgs. These packages were installed diff --git a/include/xbps_api.h b/include/xbps_api.h index 041cfb3d831..85e8818a335 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -28,6 +28,7 @@ #include #include +#include #define NDEBUG #include @@ -86,8 +87,17 @@ int xbps_humanize_number(char *, size_t, int64_t, const char *, int, int); /* From lib/findpkg.c */ +struct repository_data { + SIMPLEQ_ENTRY(repository_data) chain; + prop_dictionary_t rd_repod; +}; +SIMPLEQ_HEAD(, repository_data) repodata_queue; + int xbps_prepare_pkg(const char *); -prop_dictionary_t xbps_get_pkg_props(const char *); +int xbps_find_new_pkg(const char *, prop_dictionary_t); +int xbps_prepare_repolist_data(void); +void xbps_release_repolist_data(void); +prop_dictionary_t xbps_get_pkg_props(void); /* From lib/register.c */ int xbps_register_pkg(prop_dictionary_t, bool, bool); @@ -100,8 +110,7 @@ int xbps_requiredby_pkg_remove(const char *); int xbps_unpack_binary_pkg(prop_dictionary_t); /* From lib/depends.c */ -int xbps_find_deps_in_pkg(prop_dictionary_t, prop_dictionary_t, - prop_object_iterator_t); +int xbps_find_deps_in_pkg(prop_dictionary_t, prop_dictionary_t); /* From lib/plist.c */ bool xbps_add_obj_to_dict(prop_dictionary_t, prop_object_t, @@ -121,6 +130,8 @@ prop_dictionary_t xbps_find_pkg_from_plist(const char *, const char *); prop_dictionary_t xbps_find_pkg_installed_from_plist(const char *); bool xbps_find_string_in_array(prop_array_t, const char *); +prop_dictionary_t xbps_get_regpkgdb_dict(void); +void xbps_release_regpkgdb_dict(void); prop_object_iterator_t xbps_get_array_iter_from_dict(prop_dictionary_t, const char *); diff --git a/lib/depends.c b/lib/depends.c index eff6c9de5cd..7fb4d04c4b7 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -45,9 +45,7 @@ store_dependency(prop_dictionary_t master, prop_dictionary_t origind, { prop_dictionary_t dict; prop_array_t array; - size_t dirdepscnt = 0, indirdepscnt = 0; - const char *reqbyname, *repoloc, *originpkg; - bool indirectdep = false; + const char *reqbyname, *repoloc; assert(origind != NULL); assert(depd != NULL); @@ -59,25 +57,6 @@ store_dependency(prop_dictionary_t master, prop_dictionary_t origind, prop_dictionary_get_cstring_nocopy(origind, "pkgname", &reqbyname); prop_dictionary_get_cstring_nocopy(repod, "location-local", &repoloc); - /* - * Required dependency is not installed. Check if it's - * already registered in the chain, and update some objects - * or add the object into array otherwise. - */ - prop_dictionary_get_cstring_nocopy(master, "origin", &originpkg); - if (strcmp(originpkg, reqbyname)) { - indirectdep = true; - prop_dictionary_get_uint32(master, "indirectdeps_count", - &indirdepscnt); - prop_dictionary_set_uint32(master, "indirectdeps_count", - ++indirdepscnt); - } else { - prop_dictionary_get_uint32(master, "directdeps_count", - &dirdepscnt); - prop_dictionary_set_uint32(master, "directdeps_count", - ++dirdepscnt); - } - dict = prop_dictionary_copy(depd); if (dict == NULL) return errno; @@ -91,7 +70,6 @@ store_dependency(prop_dictionary_t master, prop_dictionary_t origind, * Add required objects into package dep's dictionary. */ prop_dictionary_set_cstring(dict, "repository", repoloc); - prop_dictionary_set_bool(dict, "indirect_dep", indirectdep); /* * Remove some unneeded objects. */ @@ -144,16 +122,12 @@ add_missing_reqdep(prop_dictionary_t master, const char *pkgname, } int -xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg, - prop_object_iterator_t iter) +xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg) { prop_array_t pkg_rdeps, missing_rdeps; - prop_dictionary_t repod; - prop_object_t obj; - char *plist; + struct repository_data *rdata; int rv = 0; - assert(pkg_props != NULL); assert(pkg != NULL); assert(iter != NULL); @@ -165,35 +139,20 @@ xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg, * Iterate over the repository pool and find out if we have * all available binary packages. */ - while ((obj = prop_object_iterator_next(iter)) != NULL) { - plist = - xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj)); - if (plist == NULL) - return EINVAL; - - repod = prop_dictionary_internalize_from_file(plist); - if (repod == NULL) { - free(plist); - return errno; - } - free(plist); - + SIMPLEQ_FOREACH(rdata, &repodata_queue, chain) { /* * This will find direct and indirect deps, * if any of them is not there it will be added * into the missing_deps array. */ - rv = find_repo_deps(master, repod, pkg, pkg_rdeps); + rv = find_repo_deps(master, rdata->rd_repod, pkg, pkg_rdeps); if (rv != 0) { if (rv == ENOENT) { rv = 0; - prop_object_release(repod); continue; } - prop_object_release(repod); break; } - prop_object_release(repod); } missing_rdeps = prop_dictionary_get(master, "missing_deps"); @@ -204,27 +163,10 @@ xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg, * If there are missing deps, iterate one more time * just in case that indirect deps weren't found. */ - prop_object_iterator_reset(iter); - while ((obj = prop_object_iterator_next(iter)) != NULL) { - plist = - xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj)); - if (plist == NULL) - return EINVAL; - - repod = prop_dictionary_internalize_from_file(plist); - if (repod == NULL) { - free(plist); - return errno; - } - free(plist); - - rv = find_repo_missing_deps(master, repod, pkg); - if (rv != 0 && rv != ENOENT) { - prop_object_release(repod); + SIMPLEQ_FOREACH(rdata, &repodata_queue, chain) { + rv = find_repo_missing_deps(master, rdata->rd_repod, pkg); + if (rv != 0 && rv != ENOENT) return rv; - } - - prop_object_release(repod); } return 0; diff --git a/lib/findpkg.c b/lib/findpkg.c index 8f875186753..2c9088b459d 100644 --- a/lib/findpkg.c +++ b/lib/findpkg.c @@ -34,18 +34,20 @@ #include -static int create_pkg_props_dictionary(const char *); - static prop_dictionary_t pkg_props; static int -create_pkg_props_dictionary(const char *pkgname) +create_pkg_props_dictionary(void) { prop_array_t unsorted, missing; int rv = 0; + static bool pkg_props_avail; assert(pkgname != NULL); + if (pkg_props_avail) + return 0; + pkg_props = prop_dictionary_create(); if (pkg_props == NULL) return ENOMEM; @@ -71,7 +73,7 @@ create_pkg_props_dictionary(const char *pkgname) goto fail3; } - prop_dictionary_set_cstring_nocopy(pkg_props, "origin", pkgname); + pkg_props_avail = true; return rv; @@ -86,32 +88,37 @@ fail: } prop_dictionary_t -xbps_get_pkg_props(const char *pkgname) +xbps_get_pkg_props(void) { - prop_string_t origin; - if (pkg_props == NULL || prop_dictionary_count(pkg_props) == 0) return NULL; - origin = prop_dictionary_get(pkg_props, "origin"); - if (!prop_string_equals_cstring(origin, pkgname)) - return NULL; - return prop_dictionary_copy(pkg_props); } int -xbps_prepare_pkg(const char *pkgname) +xbps_prepare_repolist_data(void) { - prop_dictionary_t repod = NULL, repolistd, pkgrd = NULL; - prop_array_t array, pkgs_array; + prop_dictionary_t dict = NULL; + prop_array_t array; prop_object_t obj; - prop_object_iterator_t repolist_iter; - const char *repoloc, *rootdir; + prop_object_iterator_t iter; + struct repository_data *rdata; + const char *rootdir; char *plist; int rv = 0; + static bool repodata_init; - assert(pkgname != NULL); + if (repodata_init == false) { + SIMPLEQ_INIT(&repodata_queue); + repodata_init = true; + } + + rdata = malloc(sizeof(struct repository_data)); + if (rdata == NULL) { + rv = errno; + goto out; + } rootdir = xbps_get_rootdir(); if (rootdir == NULL) @@ -119,79 +126,201 @@ xbps_prepare_pkg(const char *pkgname) plist = xbps_xasprintf("%s/%s/%s", rootdir, XBPS_META_PATH, XBPS_REPOLIST); - if (plist == NULL) - return EINVAL; + if (plist == NULL) { + rv = EINVAL; + goto out; + } - repolistd = prop_dictionary_internalize_from_file(plist); - if (repolistd == NULL) { + dict = prop_dictionary_internalize_from_file(plist); + if (dict == NULL) { free(plist); - return EINVAL; + rv = errno; + goto out; } free(plist); - array = prop_dictionary_get(repolistd, "repository-list"); + array = prop_dictionary_get(dict, "repository-list"); if (array == NULL) { - prop_object_release(repolistd); - return EINVAL; + rv = EINVAL; + goto out; } - repolist_iter = prop_array_iterator(array); - if (repolist_iter == NULL) { - prop_object_release(repolistd); - return ENOMEM; + iter = prop_array_iterator(array); + if (iter == NULL) { + rv = ENOMEM; + goto out; } - while ((obj = prop_object_iterator_next(repolist_iter)) != NULL) { + while ((obj = prop_object_iterator_next(iter)) != NULL) { /* - * Iterate over the repository pool and find out if we have - * the binary package. + * Iterate over the repository pool and add the dictionary + * for current repository into the queue. */ plist = xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj)); - if (plist == NULL) - return EINVAL; + if (plist == NULL) { + rv = EINVAL; + goto out2; + } - repod = prop_dictionary_internalize_from_file(plist); - if (repod == NULL) { + rdata->rd_repod = prop_dictionary_internalize_from_file(plist); + if (rdata->rd_repod == NULL) { free(plist); - return errno; + rv = errno; + goto out2; } free(plist); + SIMPLEQ_INSERT_TAIL(&repodata_queue, rdata, chain); + } +out2: + prop_object_iterator_release(iter); +out: + prop_object_release(dict); + if (rv != 0) + xbps_release_repolist_data(); + + return rv; + +} + +void +xbps_release_repolist_data(void) +{ + struct repository_data *rdata; + + while ((rdata = SIMPLEQ_FIRST(&repodata_queue)) != NULL) { + SIMPLEQ_REMOVE(&repodata_queue, rdata, repository_data, chain); + prop_object_release(rdata->rd_repod); + free(rdata); + } +} + +int +xbps_find_new_pkg(const char *pkgname, prop_dictionary_t instpkg) +{ + prop_dictionary_t pkgrd = NULL; + prop_array_t unsorted; + struct repository_data *rdata; + const char *repoloc, *repover, *instver; + int rv = 0; + + assert(pkgname != NULL); + assert(instpkg != NULL); + + SIMPLEQ_FOREACH(rdata, &repodata_queue, chain) { /* * Get the package dictionary from current repository. * If it's not there, pass to the next repository. */ - pkgrd = xbps_find_pkg_in_dict(repod, "packages", pkgname); - if (pkgrd == NULL) { - prop_object_release(repod); - continue; - } - break; - } - prop_object_iterator_reset(repolist_iter); + pkgrd = xbps_find_pkg_in_dict(rdata->rd_repod, + "packages", pkgname); + if (pkgrd != NULL) { + /* + * Check if installed version is >= than the + * one available in current repository. + */ + prop_dictionary_get_cstring_nocopy(instpkg, + "version", &instver); + prop_dictionary_get_cstring_nocopy(pkgrd, + "version", &repover); + if (xbps_cmpver_versions(instver, repover) >= 0) + goto out; - if (pkgrd == NULL) { - rv = EAGAIN; - goto out2; + break; + } } + if (pkgrd == NULL) + return 0; /* * Create master pkg dictionary. */ - if ((rv = create_pkg_props_dictionary(pkgname)) != 0) + if ((rv = create_pkg_props_dictionary()) != 0) goto out; /* * Set repository in pkg dictionary. */ - if (!prop_dictionary_get_cstring_nocopy(repod, + if (!prop_dictionary_get_cstring_nocopy(rdata->rd_repod, "location-local", &repoloc)) { rv = EINVAL; goto out; } prop_dictionary_set_cstring(pkgrd, "repository", repoloc); + /* + * Construct the dependency chain for this package. + */ + if ((rv = xbps_find_deps_in_pkg(pkg_props, pkgrd)) != 0) + goto out; + + /* + * Add required package dictionary into the packages + * dictionary. + */ + unsorted = prop_dictionary_get(pkg_props, "unsorted_deps"); + if (unsorted == NULL) { + rv = EINVAL; + goto out; + } + + if (!prop_array_add(unsorted, pkgrd)) + rv = errno; + +out: + if (rv != 0) + xbps_release_repolist_data(); + + return rv; +} + +int +xbps_prepare_pkg(const char *pkgname) +{ + prop_dictionary_t pkgrd = NULL; + prop_array_t pkgs_array; + struct repository_data *rdata; + const char *repoloc; + int rv = 0; + + assert(pkgname != NULL); + + if ((rv = xbps_prepare_repolist_data()) != 0) + return rv; + + SIMPLEQ_FOREACH(rdata, &repodata_queue, chain) { + /* + * Get the package dictionary from current repository. + * If it's not there, pass to the next repository. + */ + pkgrd = xbps_find_pkg_in_dict(rdata->rd_repod, + "packages", pkgname); + if (pkgrd != NULL) + break; + } + if (pkgrd == NULL) { + rv = EAGAIN; + goto out; + } + + /* + * Create master pkg dictionary. + */ + if ((rv = create_pkg_props_dictionary()) != 0) + goto out; + + /* + * Set repository in pkg dictionary. + */ + if (!prop_dictionary_get_cstring_nocopy(rdata->rd_repod, + "location-local", &repoloc)) { + rv = EINVAL; + goto out; + } + prop_dictionary_set_cstring(pkgrd, "repository", repoloc); + prop_dictionary_set_cstring(pkgrd, "origin", pkgname); + /* * Check if this package needs dependencies. */ @@ -199,8 +328,7 @@ xbps_prepare_pkg(const char *pkgname) /* * Construct the dependency chain for this package. */ - if ((rv = xbps_find_deps_in_pkg(pkg_props, pkgrd, - repolist_iter)) != 0) + if ((rv = xbps_find_deps_in_pkg(pkg_props, pkgrd)) != 0) goto out; /* @@ -218,7 +346,8 @@ xbps_prepare_pkg(const char *pkgname) rv = errno; goto out; } - if (!prop_dictionary_set(pkg_props, "packages", pkgs_array)) { + if (!prop_dictionary_set(pkg_props, "packages", + pkgs_array)) { rv = errno; goto out; } @@ -235,18 +364,11 @@ xbps_prepare_pkg(const char *pkgname) goto out; } - if (!prop_array_add(pkgs_array, pkgrd)) { + if (!prop_array_add(pkgs_array, pkgrd)) rv = errno; - goto out; - } - - prop_dictionary_remove(pkg_props, "unsorted_deps"); out: - prop_object_release(repod); -out2: - prop_object_iterator_release(repolist_iter); - prop_object_release(repolistd); + xbps_release_repolist_data(); return rv; } diff --git a/lib/plist.c b/lib/plist.c index 67239617423..d97b9f1680d 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -33,6 +33,8 @@ #include +static prop_dictionary_t regpkgdb_dict; + bool xbps_add_obj_to_dict(prop_dictionary_t dict, prop_object_t obj, const char *key) @@ -160,18 +162,14 @@ xbps_find_pkg_from_plist(const char *plist, const char *pkgname) prop_dictionary_t xbps_find_pkg_installed_from_plist(const char *pkgname) { - prop_dictionary_t pkgd; - const char *rootdir; - char *plist; + prop_dictionary_t instd, pkgd; - rootdir = xbps_get_rootdir(); - plist = xbps_xasprintf("%s/%s/%s", rootdir, - XBPS_META_PATH, XBPS_REGPKGDB); - if (plist == NULL) + instd = xbps_get_regpkgdb_dict(); + if (instd == NULL) return NULL; - pkgd = xbps_find_pkg_from_plist(plist, pkgname); - free(plist); + pkgd = xbps_find_pkg_in_dict(instd, "packages", pkgname); + xbps_release_regpkgdb_dict(); return pkgd; } @@ -202,6 +200,37 @@ xbps_find_pkg_in_dict(prop_dictionary_t dict, const char *key, return obj; } +prop_dictionary_t +xbps_get_regpkgdb_dict(void) +{ + const char *rootdir; + char *plist; + + if (regpkgdb_dict == NULL) { + rootdir = xbps_get_rootdir(); + plist = xbps_xasprintf("%s/%s/%s", rootdir, + XBPS_META_PATH, XBPS_REGPKGDB); + if (plist == NULL) + return NULL; + + regpkgdb_dict = prop_dictionary_internalize_from_file(plist); + if (regpkgdb_dict == NULL) + return NULL; + } + + return prop_dictionary_copy(regpkgdb_dict); +} + +void +xbps_release_regpkgdb_dict(void) +{ + if (regpkgdb_dict == NULL) + return; + + prop_object_release(regpkgdb_dict); + regpkgdb_dict = NULL; +} + bool xbps_find_string_in_array(prop_array_t array, const char *val) { diff --git a/lib/sortdeps.c b/lib/sortdeps.c index fa1ef65399a..2f6b11f3b58 100644 --- a/lib/sortdeps.c +++ b/lib/sortdeps.c @@ -64,7 +64,7 @@ xbps_sort_pkg_deps(prop_dictionary_t chaindeps) prop_object_t obj, obj2; prop_object_iterator_t iter, iter2; struct sorted_dependency *sdep; - size_t indirdepscnt = 0, dirdepscnt = 0, rundepscnt = 0, cnt = 0; + size_t ndeps = 0, rundepscnt = 0, cnt = 0; const char *pkgname; char *curpkgnamedep; int rv = 0; @@ -84,10 +84,7 @@ xbps_sort_pkg_deps(prop_dictionary_t chaindeps) return 0; } - prop_dictionary_get_uint32(chaindeps, "indirectdeps_count", - &indirdepscnt); - prop_dictionary_get_uint32(chaindeps, "directdeps_count", - &dirdepscnt); + ndeps = prop_array_count(unsorted); unsorted = prop_dictionary_get(chaindeps, "unsorted_deps"); iter = prop_array_iterator(unsorted); @@ -159,7 +156,7 @@ again: } /* Iterate until all deps are processed. */ - if (cnt < dirdepscnt + indirdepscnt) { + if (cnt < ndeps) { prop_object_iterator_reset(iter); goto again; } @@ -179,14 +176,16 @@ again: * Sanity check that the array contains the same number of * objects than the total number of required dependencies. */ - cnt = dirdepscnt + indirdepscnt; - if (cnt != prop_array_count(sorted)) { + if (ndeps != prop_array_count(sorted)) { rv = EINVAL; goto out; } if (!prop_dictionary_set(chaindeps, "packages", sorted)) rv = EINVAL; + + prop_dictionary_remove(chaindeps, "unsorted_deps"); + out: /* * Release resources used by temporary sorting. diff --git a/lib/util.c b/lib/util.c index 2cd63840945..d43301d25f9 100644 --- a/lib/util.c +++ b/lib/util.c @@ -125,7 +125,7 @@ xbps_check_is_installed_pkg(const char *pkg) dict = xbps_find_pkg_installed_from_plist(pkgname); if (dict == NULL) { free(pkgname); - return -1; /* not installed */ + return -2; /* not installed */ } /* Get version from installed package */