diff --git a/bin/xbps-bin/Makefile b/bin/xbps-bin/Makefile index 88d7aa9d46..0ce2ac00a1 100644 --- a/bin/xbps-bin/Makefile +++ b/bin/xbps-bin/Makefile @@ -1,5 +1,5 @@ BIN = xbps-bin -OBJS = main.o ../xbps-repo/util.o +OBJS = install.o main.o ../xbps-repo/util.o TOPDIR = ../.. include $(TOPDIR)/prog.mk diff --git a/bin/xbps-bin/defs.h b/bin/xbps-bin/defs.h new file mode 100644 index 0000000000..865a4c9514 --- /dev/null +++ b/bin/xbps-bin/defs.h @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 2009 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _XBPS_BIN_DEFS_H_ +#define _XBPS_BIN_DEFS_H_ + +void xbps_install_pkg(const char *, bool); + +#endif /* !_XBPS_BIN_DEFS_H_ */ diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c new file mode 100644 index 0000000000..2becfd80d6 --- /dev/null +++ b/bin/xbps-bin/install.c @@ -0,0 +1,233 @@ +/*- + * Copyright (c) 2009 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "defs.h" + +static void show_missing_deps(prop_dictionary_t, const char *); +static int show_missing_dep_cb(prop_object_t, void *, bool *); + +static void +show_missing_deps(prop_dictionary_t d, const char *pkgname) +{ + printf("Unable to locate some required packages for %s:\n", + pkgname); + (void)xbps_callback_array_iter_in_dict(d, "missing_deps", + show_missing_dep_cb, NULL); +} + +static int +show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done) +{ + const char *pkgname, *version; + + (void)arg; + (void)loop_done; + + prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); + prop_dictionary_get_cstring_nocopy(obj, "version", &version); + if (pkgname && version) { + printf(" * Missing binary package for: %s >= %s\n", + pkgname, version); + return 0; + } + + return EINVAL; +} + +void +xbps_install_pkg(const char *pkg, bool update) +{ + 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; + const char *repoloc, *filename, *instver, *origin; + const char *pkgname, *version; + char size[64]; + int rv = 0; + bool pkg_is_dep; + + 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); + exit(EXIT_FAILURE); + } + + prop_dictionary_get_cstring_nocopy(props, "origin", &origin); + + /* + * 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"); + exit(EXIT_FAILURE); + } + + iter = prop_array_iterator(array); + if (iter == NULL) { + printf("error: allocating array mem! (%s)\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Checking binary package file(s) integrity...\n"); + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + /* + * Use this loop to calculate total and installed + * size for all binary packages that are going to be + * downloaded/installed. + */ + prop_dictionary_get_uint64(obj, "filename-size", &tsize); + dlsize += tsize; + tsize = 0; + prop_dictionary_get_uint64(obj, "installed_size", &tsize); + instsize += tsize; + tsize = 0; + + 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)); + exit(EXIT_FAILURE); + } else if (rv != 0 && rv == ERANGE) { + printf("Hash doesn't match for %s!\n", filename); + exit(EXIT_FAILURE); + } + } + prop_object_iterator_reset(iter); + + /* + * Show total download/installed size for all required packages. + */ + if (xbps_humanize_number(size, 5, (int64_t)dlsize, + "", HN_AUTOSCALE, HN_NOSPACE) == -1) { + printf("error: humanize_number %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + printf("Total download size: %s\n", size); + if (xbps_humanize_number(size, 5, (int64_t)instsize, + "", HN_AUTOSCALE, HN_NOSPACE) == -1) { + printf("error: humanize_number2 %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + printf("Total installed size: %s\n", size); + + /* + * Install all packages, the list is already sorted. + */ + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); + prop_dictionary_get_cstring_nocopy(obj, "version", &version); + if (strcmp(origin, pkgname)) + pkg_is_dep = true; + + if (update) { + /* + * 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, version); + 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, update); + if (rv != 0) { + printf("error: removing %s-%s (%s)\n", + pkgname, instver, strerror(rv)); + exit(EXIT_FAILURE); + } + + } else { + printf("Installing %s%s-%s ...\n", + pkg_is_dep ? "dependency " : "", pkgname, version); + } + /* + * Unpack binary package. + */ + if ((rv = xbps_unpack_binary_pkg(obj)) != 0) { + printf("error: unpacking %s-%s (%s)\n", pkgname, + version, strerror(rv)); + exit(EXIT_FAILURE); + } + /* + * Register binary package. + */ + if ((rv = xbps_register_pkg(obj, update, pkg_is_dep)) != 0) { + printf("error: registering %s-%s! (%s)\n", + pkgname, version, strerror(rv)); + exit(EXIT_FAILURE); + } + pkg_is_dep = false; + } + prop_object_iterator_release(iter); + + exit(EXIT_SUCCESS); +} diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index 7fe6cf0bce..514f3a87f8 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -34,11 +34,10 @@ #include #include +#include "defs.h" #include "../xbps-repo/util.h" static void usage(void); -static void show_missing_deps(prop_dictionary_t, const char *); -static int show_missing_dep_cb(prop_object_t, void *, bool *); static int list_pkgs_in_dict(prop_object_t, void *, bool *); static void @@ -87,34 +86,7 @@ list_pkgs_in_dict(prop_object_t obj, void *arg, bool *loop_done) prop_dictionary_get_cstring_nocopy(obj, "version", &version); prop_dictionary_get_cstring_nocopy(obj, "short_desc", &short_desc); if (pkgname && version && short_desc) { - printf("%s (%s)\t%s\n", pkgname, version, short_desc); - return 0; - } - - return EINVAL; -} - -static void -show_missing_deps(prop_dictionary_t d, const char *pkgname) -{ - printf("Unable to locate some required packages for %s:\n", - pkgname); - (void)xbps_callback_array_iter_in_dict(d, "missing_deps", - show_missing_dep_cb, NULL); -} - -static int -show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done) -{ - const char *pkgname, *version; - (void)arg; - (void)loop_done; - - prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); - prop_dictionary_get_cstring_nocopy(obj, "version", &version); - if (pkgname && version) { - printf("\tmissing binary package for: %s >= %s\n", - pkgname, version); + printf("%s-%s\t%s\n", pkgname, version, short_desc); return 0; } @@ -196,41 +168,14 @@ main(int argc, char **argv) if (argc != 2) usage(); - rv = xbps_install_binary_pkg(argv[1], false); - if (rv != 0) { - if (rv == EAGAIN) { - printf("Unable to locate %s in " - "repository pool.\n", argv[1]); - } else if (rv == ENOENT) { - dict = xbps_get_pkg_deps_dictionary(); - if (dict) - show_missing_deps(dict, argv[1]); - } else if (rv == EEXIST) { - printf("Package '%s' is already up to date.\n", - argv[1]); - exit(EXIT_SUCCESS); - } - - exit(EXIT_FAILURE); - } - printf("Package %s installed successfully.\n", argv[1]); + xbps_install_pkg(argv[1], false); } else if (strcasecmp(argv[0], "update") == 0) { /* Update an installed package. */ if (argc != 2) usage(); - rv = xbps_install_binary_pkg(argv[1], true); - if (rv != 0) { - if (rv == EEXIST) { - printf("Package %s is already up to date.\n", - argv[1]); - exit(EXIT_SUCCESS); - } - exit(EXIT_FAILURE); - } - - printf("Package %s updated successfully.\n", argv[1]); + xbps_install_pkg(argv[1], true); } else if (strcasecmp(argv[0], "remove") == 0) { /* Removes a binary package. */ diff --git a/doc/TODO b/doc/TODO index ef27b239eb..a358846505 100644 --- a/doc/TODO +++ b/doc/TODO @@ -19,8 +19,6 @@ xbps-bin: * Add support to handle conf_files and keep_dirs from package metadata. [PARTIALLY IMPLEMENTED] * Add support to install binary packages without any repository. - * Show binpkg size and installed size for all packages that are going - to be installed before installation happens. * Add a target to update all currently installed packages, like "apt-get dist-upgrade". [IN PROGRESS] * Add a flag to reinstall a package version that is already installed, diff --git a/include/xbps_api.h b/include/xbps_api.h index 295136f8a3..386335e472 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -80,19 +80,23 @@ int xbps_file_chdir_exec(const char *, const char *, ...); int xbps_humanize_number(char *, size_t, int64_t, const char *, int, int); -/* From lib/install.c, lib/depends.c and lib/unpack.c */ -int xbps_install_pkg_deps(const char *, bool); -int xbps_install_binary_pkg(const char *, bool); -int xbps_install_binary_pkg_fini(prop_dictionary_t, - prop_dictionary_t, bool); +/* From lib/findpkg.c */ +int xbps_prepare_pkg(const char *); +prop_dictionary_t xbps_get_pkg_props(const char *); + +/* From lib/register.c */ int xbps_register_pkg(prop_dictionary_t, bool, bool); -int xbps_unpack_binary_pkg(prop_dictionary_t, prop_dictionary_t); + +/* From lib/requiredby.c */ int xbps_requiredby_pkg_add(prop_array_t, prop_dictionary_t); int xbps_requiredby_pkg_remove(const char *); -int xbps_find_deps_in_pkg(prop_dictionary_t, - prop_object_iterator_t); -prop_dictionary_t xbps_get_pkg_deps_dictionary(void); +/* From lib/unpack.c */ +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); /* From lib/plist.c */ bool xbps_add_obj_to_dict(prop_dictionary_t, prop_object_t, diff --git a/lib/Makefile b/lib/Makefile index f0e581c308..cbca0a0390 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -8,8 +8,8 @@ LIBXBPS_SO = $(LIBXBPS).$(MAJOR).$(MINOR).$(MICRO) LIBXBPS = libxbps.so LIBXBPS_LDFLAGS = -larchive -lprop -shared -Wl,-soname,$(LIBXBPS).$(MAJOR) -OBJECTS = cmpver.o depends.o fexec.o humanize_number.o install.o -OBJECTS += orphans.o plist.o remove.o repository.o requiredby.o +OBJECTS = cmpver.o depends.o fexec.o findpkg.o humanize_number.o +OBJECTS += orphans.o plist.o register.o remove.o repository.o requiredby.o OBJECTS += sha256.o sortdeps.o unpack.o util.o all: $(LIBXBPS) diff --git a/lib/depends.c b/lib/depends.c index 2934b078b8..8763a2fc06 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -32,70 +32,21 @@ #include -static int add_missing_reqdep(const char *, const char *); -static int find_pkg_deps_from_repo(prop_dictionary_t, prop_dictionary_t, - prop_array_t); -static int find_pkg_missing_deps_from_repo(prop_dictionary_t, - prop_dictionary_t); - -static prop_dictionary_t chaindeps; -static bool deps_dict; - -/* - * Creates the dictionary to store the dependency chain. - */ -static int -create_deps_dictionary(void) -{ - prop_array_t unsorted, missing; - int rv = 0; - - chaindeps = prop_dictionary_create(); - if (chaindeps == NULL) - return ENOMEM; - - missing = prop_array_create(); - if (missing == NULL) { - rv = ENOMEM; - goto fail; - } - - unsorted = prop_array_create(); - if (unsorted == NULL) { - rv = ENOMEM; - goto fail2; - } - - if (!xbps_add_obj_to_dict(chaindeps, missing, "missing_deps")) { - rv = EINVAL; - goto fail3; - } - if (!xbps_add_obj_to_dict(chaindeps, unsorted, "unsorted_deps")) { - rv = EINVAL; - goto fail3; - } - return rv; - -fail3: - prop_object_release(unsorted); -fail2: - prop_object_release(missing); -fail: - prop_object_release(chaindeps); - - return rv; -} +static int add_missing_reqdep(prop_dictionary_t, const char *, + const char *); +static int find_repo_deps(prop_dictionary_t, prop_dictionary_t, + prop_dictionary_t, prop_array_t); +static int find_repo_missing_deps(prop_dictionary_t, prop_dictionary_t, + prop_dictionary_t); static int -store_dependency(prop_dictionary_t origind, prop_dictionary_t depd, - prop_dictionary_t repod) +store_dependency(prop_dictionary_t master, prop_dictionary_t origind, + prop_dictionary_t depd, prop_dictionary_t repod) { prop_dictionary_t dict; - prop_array_t array, rundeps_array; + prop_array_t array; size_t dirdepscnt = 0, indirdepscnt = 0; - const char *pkgname, *version, *reqbyname, *arch; - const char *repoloc, *binfile, *originpkg; - const char *short_desc, *sha256; + const char *reqbyname, *repoloc, *originpkg; bool indirectdep = false; assert(origind != NULL); @@ -105,12 +56,6 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd, /* * Get some info about dependencies and current repository. */ - prop_dictionary_get_cstring_nocopy(depd, "pkgname", &pkgname); - prop_dictionary_get_cstring_nocopy(depd, "version", &version); - prop_dictionary_get_cstring_nocopy(depd, "filename", &binfile); - prop_dictionary_get_cstring_nocopy(depd, "short_desc", &short_desc); - prop_dictionary_get_cstring_nocopy(depd, "architecture", &arch); - prop_dictionary_get_cstring_nocopy(depd, "filename-sha256", &sha256); prop_dictionary_get_cstring_nocopy(origind, "pkgname", &reqbyname); prop_dictionary_get_cstring_nocopy(repod, "location-local", &repoloc); @@ -119,48 +64,41 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd, * already registered in the chain, and update some objects * or add the object into array otherwise. */ - prop_dictionary_get_cstring_nocopy(chaindeps, "origin", &originpkg); + prop_dictionary_get_cstring_nocopy(master, "origin", &originpkg); if (strcmp(originpkg, reqbyname)) { indirectdep = true; - prop_dictionary_get_uint32(chaindeps, "indirectdeps_count", + prop_dictionary_get_uint32(master, "indirectdeps_count", &indirdepscnt); - prop_dictionary_set_uint32(chaindeps, "indirectdeps_count", + prop_dictionary_set_uint32(master, "indirectdeps_count", ++indirdepscnt); } else { - prop_dictionary_get_uint32(chaindeps, "directdeps_count", + prop_dictionary_get_uint32(master, "directdeps_count", &dirdepscnt); - prop_dictionary_set_uint32(chaindeps, "directdeps_count", + prop_dictionary_set_uint32(master, "directdeps_count", ++dirdepscnt); } - /* - * Create package dep's dictionary and array. - */ - dict = prop_dictionary_create(); + dict = prop_dictionary_copy(depd); if (dict == NULL) return errno; - array = prop_dictionary_get(chaindeps, "unsorted_deps"); + array = prop_dictionary_get(master, "unsorted_deps"); if (array == NULL) { prop_object_release(dict); return errno; } - /* * Add required objects into package dep's dictionary. */ - prop_dictionary_set_cstring(dict, "pkgname", pkgname); - prop_dictionary_set_cstring(dict, "version", version); - rundeps_array = prop_dictionary_get(depd, "run_depends"); - if (rundeps_array && prop_array_count(rundeps_array) > 0) - prop_dictionary_set(dict, "run_depends", rundeps_array); - prop_dictionary_set_cstring(dict, "repository", repoloc); - prop_dictionary_set_cstring(dict, "filename", binfile); - prop_dictionary_set_cstring(dict, "short_desc", short_desc); prop_dictionary_set_bool(dict, "indirect_dep", indirectdep); - prop_dictionary_set_cstring(dict, "architecture", arch); - prop_dictionary_set_cstring(dict, "filename-sha256", sha256); + /* + * Remove some unneeded objects. + */ + prop_dictionary_remove(dict, "conf_files"); + prop_dictionary_remove(dict, "keep_dirs"); + prop_dictionary_remove(dict, "maintainer"); + prop_dictionary_remove(dict, "long_desc"); /* * Add the dictionary into the array. @@ -174,21 +112,23 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd, } static int -add_missing_reqdep(const char *pkgname, const char *version) +add_missing_reqdep(prop_dictionary_t master, const char *pkgname, + const char *version) { prop_array_t array; prop_dictionary_t depd; + assert(master != NULL); assert(pkgname != NULL); assert(version != NULL); /* * Adds a package into the missing deps array. */ - if (xbps_find_pkg_in_dict(chaindeps, "missing_deps", pkgname)) + if (xbps_find_pkg_in_dict(master, "missing_deps", pkgname)) return EEXIST; - array = prop_dictionary_get(chaindeps, "missing_deps"); + array = prop_dictionary_get(master, "missing_deps"); depd = prop_dictionary_create(); if (depd == NULL) return ENOMEM; @@ -204,7 +144,8 @@ add_missing_reqdep(const char *pkgname, const char *version) } int -xbps_find_deps_in_pkg(prop_dictionary_t pkg, prop_object_iterator_t iter) +xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg, + prop_object_iterator_t iter) { prop_array_t pkg_rdeps, missing_rdeps; prop_dictionary_t repod; @@ -212,6 +153,7 @@ xbps_find_deps_in_pkg(prop_dictionary_t pkg, prop_object_iterator_t iter) char *plist; int rv = 0; + assert(pkg_props != NULL); assert(pkg != NULL); assert(iter != NULL); @@ -241,7 +183,7 @@ xbps_find_deps_in_pkg(prop_dictionary_t pkg, prop_object_iterator_t iter) * if any of them is not there it will be added * into the missing_deps array. */ - rv = find_pkg_deps_from_repo(repod, pkg, pkg_rdeps); + rv = find_repo_deps(master, repod, pkg, pkg_rdeps); if (rv != 0) { if (rv == ENOENT) { rv = 0; @@ -254,7 +196,7 @@ xbps_find_deps_in_pkg(prop_dictionary_t pkg, prop_object_iterator_t iter) prop_object_release(repod); } - missing_rdeps = prop_dictionary_get(chaindeps, "missing_deps"); + missing_rdeps = prop_dictionary_get(master, "missing_deps"); if (prop_array_count(missing_rdeps) == 0) return 0; @@ -276,7 +218,7 @@ xbps_find_deps_in_pkg(prop_dictionary_t pkg, prop_object_iterator_t iter) } free(plist); - rv = find_pkg_missing_deps_from_repo(repod, pkg); + rv = find_repo_missing_deps(master, repod, pkg); if (rv != 0 && rv != ENOENT) { prop_object_release(repod); return rv; @@ -288,17 +230,9 @@ xbps_find_deps_in_pkg(prop_dictionary_t pkg, prop_object_iterator_t iter) return 0; } -prop_dictionary_t -xbps_get_pkg_deps_dictionary(void) -{ - if (!deps_dict) - return NULL; - - return prop_dictionary_copy(chaindeps); -} - static int -find_pkg_missing_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg) +find_repo_missing_deps(prop_dictionary_t master, prop_dictionary_t repo, + prop_dictionary_t pkg) { prop_array_t array; prop_dictionary_t curpkgd; @@ -310,7 +244,7 @@ find_pkg_missing_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg) assert(repo != NULL); assert(pkg != NULL); - array = prop_dictionary_get(chaindeps, "missing_deps"); + array = prop_dictionary_get(master, "missing_deps"); if (prop_array_count(array) == 0) return 0; @@ -327,7 +261,7 @@ find_pkg_missing_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg) */ curpkgd = xbps_find_pkg_in_dict(repo, "packages", pkgname); if (curpkgd == NULL) { - rv = add_missing_reqdep(pkgname, version); + rv = add_missing_reqdep(master, pkgname, version); if (rv != 0 && rv != EEXIST) break; else { @@ -338,12 +272,12 @@ find_pkg_missing_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg) /* * Package is on repo, add it into the dictionary. */ - if ((rv = store_dependency(pkg, curpkgd, repo)) != 0) + if ((rv = store_dependency(master, pkg, curpkgd, repo)) != 0) break; /* * Remove package from missing_deps array now. */ - rv = xbps_remove_pkg_from_dict(chaindeps, + rv = xbps_remove_pkg_from_dict(master, "missing_deps", pkgname); if (rv != 0 && rv != ENOENT) break; @@ -356,8 +290,8 @@ find_pkg_missing_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg) } static int -find_pkg_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg, - prop_array_t pkg_rdeps) +find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, + prop_dictionary_t pkg, prop_array_t pkg_rdeps) { prop_dictionary_t curpkgd; prop_array_t curpkg_rdeps; @@ -376,20 +310,6 @@ find_pkg_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg, iter = prop_array_iterator(pkg_rdeps); if (iter == NULL) return ENOMEM; - /* - * Save the name of the origin package once. - */ - if (deps_dict == false) { - deps_dict = true; - rv = create_deps_dictionary(); - if (rv != 0) { - prop_object_iterator_release(iter); - return rv; - } - prop_dictionary_get_cstring_nocopy(pkg, "pkgname", &reqpkg); - prop_dictionary_set_cstring_nocopy(chaindeps, - "origin", reqpkg); - } /* * Iterate over the list of required run dependencies for @@ -410,19 +330,17 @@ find_pkg_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg, * Check if package is already added in the * array of unsorted deps. */ - if (xbps_find_pkg_in_dict(chaindeps, "unsorted_deps", - pkgname)) { + if (xbps_find_pkg_in_dict(master, "unsorted_deps", pkgname)) { free(pkgname); continue; } - /* * If required package is not in repo, add it into the * missing deps array and pass to the next one. */ curpkgd = xbps_find_pkg_in_dict(repo, "packages", pkgname); if (curpkgd == NULL) { - rv = add_missing_reqdep(pkgname, reqvers); + rv = add_missing_reqdep(master, pkgname, reqvers); free(pkgname); if (rv != 0 && rv != EEXIST) break; @@ -431,104 +349,36 @@ find_pkg_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg, continue; } } - /* * Package is on repo, add it into the dictionary. */ - if ((rv = store_dependency(pkg, curpkgd, repo)) != 0) { + if ((rv = store_dependency(master, pkg, curpkgd, repo)) != 0) { free(pkgname); break; } - /* * Remove package from missing_deps now it's been found. */ - rv = xbps_remove_pkg_from_dict(chaindeps, + rv = xbps_remove_pkg_from_dict(master, "missing_deps", pkgname); if (rv != 0 && rv != ENOENT) { free(pkgname); break; } free(pkgname); - /* * If package doesn't have rundeps, pass to the next one. */ curpkg_rdeps = prop_dictionary_get(curpkgd, "run_depends"); if (curpkg_rdeps == NULL) continue; - /* * Iterate on required pkg to find more deps. */ - if (!find_pkg_deps_from_repo(repo, curpkgd, curpkg_rdeps)) + if (!find_repo_deps(master, repo, curpkgd, curpkg_rdeps)) continue; } prop_object_iterator_release(iter); return rv; } - -int -xbps_install_pkg_deps(const char *pkgname, bool update) -{ - prop_array_t required, missing; - prop_object_t obj; - prop_object_iterator_t iter; - const char *repoloc; - int rv = 0; - - /* - * If origin object in chaindeps is not the same, bail out. - */ - obj = prop_dictionary_get(chaindeps, "origin"); - if (obj == NULL || !prop_string_equals_cstring(obj, pkgname)) - return EINVAL; - /* - * If there are missing deps, bail out. - */ - missing = prop_dictionary_get(chaindeps, "missing_deps"); - if (prop_array_count(missing) > 0) - return ENOTSUP; - /* - * Sort the dependency chain into an array. - */ - printf("Sorting dependency list...\n"); - if ((rv = xbps_sort_pkg_deps(chaindeps)) != 0) - return rv; - - required = prop_dictionary_get(chaindeps, "required_deps"); - if (required == NULL) - return 0; - - iter = prop_array_iterator(required); - if (iter == NULL) - return ENOMEM; - - /* - * Check the SHA256 hash for any binary package that's going - * to be installed. - */ - while ((obj = prop_object_iterator_next(iter)) != NULL) { - prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); - rv = xbps_check_pkg_file_hash(obj, repoloc); - if (rv != 0) - goto out; - } - prop_object_iterator_reset(iter); - - /* - * Install all required dependencies, previously sorted. - */ - printf("Installing required dependencies...\n"); - while ((obj = prop_object_iterator_next(iter)) != NULL) { - rv = xbps_install_binary_pkg_fini(NULL, obj, update); - if (rv != 0) - break; - } - -out: - prop_object_iterator_release(iter); - - return rv; -} diff --git a/lib/findpkg.c b/lib/findpkg.c new file mode 100644 index 0000000000..69df407609 --- /dev/null +++ b/lib/findpkg.c @@ -0,0 +1,238 @@ +/*- + * Copyright (c) 2009 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static int create_pkg_props_dictionary(const char *); + +static prop_dictionary_t pkg_props; + +static int +create_pkg_props_dictionary(const char *pkgname) +{ + prop_array_t unsorted, missing; + int rv = 0; + + assert(pkgname != NULL); + + pkg_props = prop_dictionary_create(); + if (pkg_props == NULL) + return ENOMEM; + + missing = prop_array_create(); + if (missing == NULL) { + rv = ENOMEM; + goto fail; + } + + unsorted = prop_array_create(); + if (unsorted == NULL) { + rv = ENOMEM; + goto fail2; + } + + if (!xbps_add_obj_to_dict(pkg_props, missing, "missing_deps")) { + rv = EINVAL; + goto fail3; + } + if (!xbps_add_obj_to_dict(pkg_props, unsorted, "unsorted_deps")) { + rv = EINVAL; + goto fail3; + } + + prop_dictionary_set_cstring_nocopy(pkg_props, "origin", pkgname); + + return rv; + +fail3: + prop_object_release(unsorted); +fail2: + prop_object_release(missing); +fail: + prop_object_release(pkg_props); + + return rv; +} + +prop_dictionary_t +xbps_get_pkg_props(const char *pkgname) +{ + 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) +{ + prop_dictionary_t repod = NULL, repolistd, pkgrd = NULL; + prop_array_t array, pkgs_array; + prop_object_t obj; + prop_object_iterator_t repolist_iter; + const char *repoloc, *rootdir; + char *plist; + int rv = 0; + + assert(pkgname != NULL); + + rootdir = xbps_get_rootdir(); + if (rootdir == NULL) + rootdir = ""; + + plist = xbps_xasprintf("%s/%s/%s", rootdir, + XBPS_META_PATH, XBPS_REPOLIST); + if (plist == NULL) + return EINVAL; + + repolistd = prop_dictionary_internalize_from_file(plist); + if (repolistd == NULL) { + free(plist); + return EINVAL; + } + free(plist); + + array = prop_dictionary_get(repolistd, "repository-list"); + if (array == NULL) { + prop_object_release(repolistd); + return EINVAL; + } + + repolist_iter = prop_array_iterator(array); + if (repolist_iter == NULL) { + prop_object_release(repolistd); + return ENOMEM; + } + + while ((obj = prop_object_iterator_next(repolist_iter)) != NULL) { + /* + * Iterate over the repository pool and find out if we have + * the binary package. + */ + 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); + + /* + * 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); + + if (pkgrd == NULL) { + rv = EAGAIN; + goto out2; + } + + /* + * Create master pkg dictionary. + */ + if ((rv = create_pkg_props_dictionary(pkgname)) != 0) + goto out; + + /* + * Set repository in pkg dictionary. + */ + if (!prop_dictionary_get_cstring_nocopy(repod, + "location-local", &repoloc)) { + rv = EINVAL; + goto out; + } + prop_dictionary_set_cstring(pkgrd, "repository", repoloc); + + /* + * Check if this package needs dependencies. + */ + if (xbps_pkg_has_rundeps(pkgrd)) { + /* + * Construct the dependency chain for this package. + */ + if ((rv = xbps_find_deps_in_pkg(pkg_props, pkgrd, + repolist_iter)) != 0) + goto out; + + /* + * Sort the dependency chain for this package. + */ + if ((rv = xbps_sort_pkg_deps(pkg_props)) != 0) + goto out; + } + + /* + * Add required package dictionary into the packages + * dictionary. + */ + pkgs_array = prop_dictionary_get(pkg_props, "packages"); + if (pkgs_array == NULL || + prop_object_type(pkgs_array) != PROP_TYPE_ARRAY) { + rv = EINVAL; + goto out; + } + + 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); + + return rv; +} diff --git a/lib/install.c b/lib/register.c similarity index 50% rename from lib/install.c rename to lib/register.c index 3d2840c2cc..534ee99e19 100644 --- a/lib/install.c +++ b/lib/register.c @@ -34,197 +34,6 @@ #include -int -xbps_install_binary_pkg_fini(prop_dictionary_t repo, prop_dictionary_t pkgrd, - bool update) -{ - prop_dictionary_t instpkg; - const char *pkgname, *version, *instver; - int rv = 0; - bool automatic = false; - - assert(pkg != NULL); - prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname); - prop_dictionary_get_cstring_nocopy(pkgrd, "version", &version); - - if (repo == false) - automatic = true; - - if (update == true) { - /* - * Update a package, firstly removing current package. - */ - instpkg = xbps_find_pkg_installed_from_plist(pkgname); - if (instpkg == NULL) - return EINVAL; - - prop_dictionary_get_cstring_nocopy(instpkg, "version", - &instver); - printf("Removing current package %s-%s ...\n", pkgname, - instver); - prop_object_release(instpkg); - rv = xbps_remove_binary_pkg(pkgname, update); - if (rv != 0) - return rv; - printf("Installing new package %s-%s ...\n", pkgname, version); - } else { - printf("Installing %s%s: found version %s ...\n", - automatic ? "dependency " : "", pkgname, version); - } - (void)fflush(stdout); - - rv = xbps_unpack_binary_pkg(repo, pkgrd); - if (rv == 0) { - rv = xbps_register_pkg(pkgrd, update, automatic); - if (rv != 0) { - printf("ERROR: couldn't register %s-%s! (%s)\n", - pkgname, version, strerror(rv)); - return rv; - } - } - - return rv; -} - -int -xbps_install_binary_pkg(const char *pkgname, bool update) -{ - prop_dictionary_t repod = NULL, repolistd, pkgrd = NULL; - prop_array_t array; - prop_object_t obj; - prop_object_iterator_t repolist_iter; - const char *repoloc, *instver, *rootdir; - char *plist, *pkg; - int rv = 0; - - assert(pkgname != NULL); - - rootdir = xbps_get_rootdir(); - if (rootdir == NULL) - rootdir = ""; - - plist = xbps_xasprintf("%s/%s/%s", rootdir, - XBPS_META_PATH, XBPS_REPOLIST); - if (plist == NULL) - return EINVAL; - - repolistd = prop_dictionary_internalize_from_file(plist); - if (repolistd == NULL) { - free(plist); - return EINVAL; - } - free(plist); - plist = NULL; - - array = prop_dictionary_get(repolistd, "repository-list"); - if (array == NULL) { - prop_object_release(repolistd); - return EINVAL; - } - - repolist_iter = prop_array_iterator(array); - if (repolist_iter == NULL) { - prop_object_release(repolistd); - return ENOMEM; - } - - while ((obj = prop_object_iterator_next(repolist_iter)) != NULL) { - /* - * Iterate over the repository pool and find out if we have - * the binary package. - */ - 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); - - /* - * 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); - - if (pkgrd == NULL) { - rv = EAGAIN; - goto out2; - } - - /* - * Check if available version in repository is already - * installed, and return immediately in that case. - */ - prop_dictionary_get_cstring_nocopy(pkgrd, "version", &instver); - pkg = xbps_xasprintf("%s-%s", pkgname, instver); - if (pkg == NULL) { - rv = errno; - goto out; - } - if (xbps_check_is_installed_pkg(pkg) == 0) { - free(pkg); - rv = EEXIST; - goto out; - } - free(pkg); - - /* - * Check SHA256 hash for binary package before anything else. - */ - if (!prop_dictionary_get_cstring_nocopy(repod, - "location-local", &repoloc)) { - rv = EINVAL; - goto out; - } - - if ((rv = xbps_check_pkg_file_hash(pkgrd, repoloc)) != 0) - goto out; - - /* - * Check if this package needs dependencies. - */ - if (xbps_pkg_has_rundeps(pkgrd)) { - /* - * Construct the dependency chain for this package. - */ - printf("Finding required dependencies...\n"); - if ((rv = xbps_find_deps_in_pkg(pkgrd, repolist_iter)) != 0) - goto out; - - /* - * Install all required dependencies and the package itself. - */ - rv = xbps_install_pkg_deps(pkgname, update); - if (rv != 0) - goto out; - } - - /* - * Finally install the binary package that was requested by - * the client. - */ - rv = xbps_install_binary_pkg_fini(repod, pkgrd, update); -out: - prop_object_release(repod); -out2: - prop_object_iterator_release(repolist_iter); - prop_object_release(repolistd); - - return rv; -} - static prop_dictionary_t make_dict_from_pkg(const char *name, const char *ver, const char *desc) { diff --git a/lib/sortdeps.c b/lib/sortdeps.c index 73cf4e6649..7a032cd3ed 100644 --- a/lib/sortdeps.c +++ b/lib/sortdeps.c @@ -79,7 +79,7 @@ xbps_sort_pkg_deps(prop_dictionary_t chaindeps) */ unsorted = prop_dictionary_get(chaindeps, "unsorted_deps"); if (prop_array_count(unsorted) == 0) { - prop_object_release(sorted); + prop_dictionary_set(chaindeps, "packages", sorted); return 0; } @@ -185,7 +185,7 @@ again: goto out; } - if (!prop_dictionary_set(chaindeps, "required_deps", sorted)) + if (!prop_dictionary_set(chaindeps, "packages", sorted)) rv = EINVAL; out: /* diff --git a/lib/unpack.c b/lib/unpack.c index efac0944d6..4b080b2ef1 100644 --- a/lib/unpack.c +++ b/lib/unpack.c @@ -39,7 +39,7 @@ static int unpack_archive_init(prop_dictionary_t, const char *); static int unpack_archive_fini(struct archive *, prop_dictionary_t); int -xbps_unpack_binary_pkg(prop_dictionary_t repo, prop_dictionary_t pkg) +xbps_unpack_binary_pkg(prop_dictionary_t pkg) { prop_string_t filename, repoloc, arch; char *binfile; @@ -47,13 +47,14 @@ xbps_unpack_binary_pkg(prop_dictionary_t repo, prop_dictionary_t pkg) assert(pkg != NULL); - /* Append filename to the full path for binary pkg */ + /* + * Append filename to the full path for binary pkg. + */ filename = prop_dictionary_get(pkg, "filename"); arch = prop_dictionary_get(pkg, "architecture"); - if (repo) - repoloc = prop_dictionary_get(repo, "location-local"); - else - repoloc = prop_dictionary_get(pkg, "repository"); + repoloc = prop_dictionary_get(pkg, "repository"); + if (filename == NULL || arch == NULL || repoloc == NULL) + return ENOTSUP; binfile = xbps_xasprintf("%s/%s/%s", prop_string_cstring_nocopy(repoloc), diff --git a/lib/util.c b/lib/util.c index d918b1cff8..90faffc15a 100644 --- a/lib/util.c +++ b/lib/util.c @@ -100,20 +100,9 @@ xbps_check_pkg_file_hash(prop_dictionary_t pkgd, const char *repoloc) if (binfile == NULL) return EINVAL; - printf("Checking SHA256 for %s ... ", filename); - (void)fflush(stdout); - rv = xbps_check_file_hash(binfile, sha256); - if (rv != 0 && rv != ERANGE) - printf("failed (%s)\n", strerror(rv)); - else if (rv == ERANGE) - printf("failed! aborting installation.\n"); - else if (rv == 0) - printf("ok.\n"); - - (void)fflush(stdout); - free(binfile); + return rv; }