From 54b6d8780971c09652889e7853e18360d252d2e1 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Thu, 2 Apr 2009 02:46:36 +0200 Subject: [PATCH] Added basic support to update a single package via "xbps-bin update foo". --HG-- extra : convert_revision : 7214ab270ccb57a327afeed94f6a2efc4738442d --- bin/xbps-bin/main.c | 13 ++++- bin/xbps-pkgdb/main.c | 10 +++- include/install.h | 14 ++--- lib/depends.c | 4 +- lib/install.c | 128 ++++++++++++++++++++++++++++-------------- lib/requiredby.c | 46 ++++++++++++++- lib/unpack.c | 24 ++++---- 7 files changed, 174 insertions(+), 65 deletions(-) diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index dc4fd2817eb..bcf28adfcff 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -214,7 +214,7 @@ main(int argc, char **argv) if (argc != 2) usage(); - rv = xbps_install_binary_pkg(argv[1]); + rv = xbps_install_binary_pkg(argv[1], false); if (rv != 0) { if (rv == EAGAIN) { printf("Unable to locate %s in " @@ -233,6 +233,17 @@ main(int argc, char **argv) } printf("Package %s installed successfully.\n", argv[1]); + } 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) + exit(EXIT_FAILURE); + + printf("Package %s updated successfully.\n", argv[1]); + } else if (strcasecmp(argv[0], "remove") == 0) { /* Removes a binary package. */ if (argc != 2) diff --git a/bin/xbps-pkgdb/main.c b/bin/xbps-pkgdb/main.c index f70aad905ee..083425516df 100644 --- a/bin/xbps-pkgdb/main.c +++ b/bin/xbps-pkgdb/main.c @@ -130,8 +130,14 @@ main(int argc, char **argv) if (argc != 4) usage(); - rv = xbps_register_pkg(NULL, argv[1], argv[2], - argv[3], automatic); + dict = prop_dictionary_create(); + if (dict == NULL) + exit(EXIT_FAILURE); + prop_dictionary_set_cstring_nocopy(dict, "pkgname", argv[1]); + prop_dictionary_set_cstring_nocopy(dict, "version", argv[2]); + prop_dictionary_set_cstring_nocopy(dict, "short_desc", argv[3]); + + rv = xbps_register_pkg(dict, false, automatic); if (rv == EEXIST) { printf("%s=> %s-%s already registered.\n", in_chroot ? "[chroot] " : "", argv[1], argv[2]); diff --git a/include/install.h b/include/install.h index a59d60a72b4..bd13af186f1 100644 --- a/include/install.h +++ b/include/install.h @@ -27,13 +27,13 @@ #define _XBPS_INSTALL_H_ /* From lib/install.c, lib/depends.c and lib/unpack.c */ -int xbps_install_pkg_deps(const char *); -int xbps_install_binary_pkg(const char *); -int xbps_install_binary_pkg_fini(prop_dictionary_t, prop_dictionary_t); -int xbps_register_pkg(prop_dictionary_t, const char *, const char *, - const char *, bool); -int xbps_unpack_binary_pkg(prop_dictionary_t, prop_dictionary_t); -int xbps_requiredby_pkg_add(prop_array_t, prop_dictionary_t); +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); +int xbps_register_pkg(prop_dictionary_t, bool, bool); +int xbps_unpack_binary_pkg(prop_dictionary_t, prop_dictionary_t, bool); +int xbps_requiredby_pkg_add(prop_array_t, prop_dictionary_t, bool); int xbps_requiredby_pkg_remove(const char *); int xbps_find_deps_in_pkg(prop_dictionary_t); diff --git a/lib/depends.c b/lib/depends.c index 89463b60182..5b996c22258 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -547,7 +547,7 @@ find_pkg_deps_from_repo(prop_dictionary_t repo, prop_dictionary_t pkg, } int -xbps_install_pkg_deps(const char *pkgname) +xbps_install_pkg_deps(const char *pkgname, bool update) { prop_array_t required, missing; prop_object_t obj; @@ -597,7 +597,7 @@ xbps_install_pkg_deps(const char *pkgname) * Install all required dependencies, previously sorted. */ while ((obj = prop_object_iterator_next(iter)) != NULL) { - rv = xbps_install_binary_pkg_fini(NULL, obj); + rv = xbps_install_binary_pkg_fini(NULL, obj, update); if (rv != 0) break; } diff --git a/lib/install.c b/lib/install.c index 0885f7ceb94..14b7c78748c 100644 --- a/lib/install.c +++ b/lib/install.c @@ -34,30 +34,48 @@ #include +struct binpkg_instargs { + const char *pkgname; + bool update; +}; + static int install_binpkg_repo_cb(prop_object_t, void *, bool *); int -xbps_install_binary_pkg_fini(prop_dictionary_t repo, prop_dictionary_t pkg) +xbps_install_binary_pkg_fini(prop_dictionary_t repo, prop_dictionary_t pkgrd, + bool update) { - const char *pkgname, *version, *desc; + prop_dictionary_t instpkg; + const char *pkgname, *version, *instver; int rv = 0; bool automatic = false; assert(pkg != NULL); - prop_dictionary_get_cstring_nocopy(pkg, "pkgname", &pkgname); - prop_dictionary_get_cstring_nocopy(pkg, "version", &version); - prop_dictionary_get_cstring_nocopy(pkg, "short_desc", &desc); + prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname); + prop_dictionary_get_cstring_nocopy(pkgrd, "version", &version); if (repo == false) automatic = true; - printf("Installing %s%s: found version %s ...\n", - automatic ? "dependency " : "", pkgname, version); + if (update == true) { + instpkg = xbps_find_pkg_installed_from_plist(pkgname); + if (instpkg == NULL) + return EINVAL; + + prop_dictionary_get_cstring_nocopy(instpkg, "version", + &instver); + printf("Updating %s-%s to %s ...\n", pkgname, + instver, version); + prop_object_release(instpkg); + } else { + printf("Installing %s%s: found version %s ...\n", + automatic ? "dependency " : "", pkgname, version); + } (void)fflush(stdout); - rv = xbps_unpack_binary_pkg(repo, pkg); + rv = xbps_unpack_binary_pkg(repo, pkgrd, update); if (rv == 0) { - rv = xbps_register_pkg(pkg, pkgname, version, desc, automatic); + rv = xbps_register_pkg(pkgrd, update, automatic); if (rv != 0) { printf("ERROR: couldn't register %s-%s! (%s)\n", pkgname, version, strerror(rv)); @@ -69,17 +87,21 @@ xbps_install_binary_pkg_fini(prop_dictionary_t repo, prop_dictionary_t pkg) } int -xbps_install_binary_pkg(const char *pkgname) +xbps_install_binary_pkg(const char *pkgname, bool update) { + struct binpkg_instargs bi; int rv = 0; assert(pkgname != NULL); + + bi.pkgname = pkgname; + bi.update = update; /* * Iterate over the repository pool and find out if we have * all available binary packages. */ rv = xbps_callback_array_iter_in_repolist(install_binpkg_repo_cb, - (void *)pkgname); + (void *)&bi); if (rv == 0 && errno != 0) return errno; @@ -90,8 +112,9 @@ static int install_binpkg_repo_cb(prop_object_t obj, void *arg, bool *cbloop_done) { prop_dictionary_t repod, pkgrd; + struct binpkg_instargs *bi = arg; size_t len = 0; - const char *repoloc, *instver, *pkgname = arg; + const char *repoloc, *instver; char *plist, *pkg; int rv = 0; @@ -110,7 +133,7 @@ install_binpkg_repo_cb(prop_object_t obj, void *arg, bool *cbloop_done) * 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); + pkgrd = xbps_find_pkg_in_dict(repod, "packages", bi->pkgname); if (pkgrd == NULL) { prop_object_release(repod); errno = EAGAIN; @@ -122,13 +145,13 @@ install_binpkg_repo_cb(prop_object_t obj, void *arg, bool *cbloop_done) * and return immediately in that case. */ prop_dictionary_get_cstring_nocopy(pkgrd, "version", &instver); - len = strlen(pkgname) + strlen(instver) + 2; + len = strlen(bi->pkgname) + strlen(instver) + 2; pkg = malloc(len); if (pkg == NULL) { rv = EINVAL; goto out; } - (void)snprintf(pkg, len, "%s-%s", pkgname, instver); + (void)snprintf(pkg, len, "%s-%s", bi->pkgname, instver); if (xbps_check_is_installed_pkg(pkg) == 0) { free(pkg); rv = EEXIST; @@ -171,12 +194,12 @@ install_binpkg_repo_cb(prop_object_t obj, void *arg, bool *cbloop_done) /* * Install all required dependencies and the package itself. */ - rv = xbps_install_pkg_deps(pkgname); + rv = xbps_install_pkg_deps(bi->pkgname, bi->update); if (rv != 0) goto out; install: - rv = xbps_install_binary_pkg_fini(repod, pkgrd); + rv = xbps_install_binary_pkg_fini(repod, pkgrd, bi->update); if (rv == 0) { *cbloop_done = true; /* Cleanup errno, just in case */ @@ -205,26 +228,28 @@ make_dict_from_pkg(const char *name, const char *ver, const char *desc) } int -xbps_register_pkg(prop_dictionary_t pkgrd, const char *pkgname, - const char *version, const char *desc, - bool automatic) +xbps_register_pkg(prop_dictionary_t pkgrd, bool update, bool automatic) { - prop_dictionary_t dict, pkgd; + prop_dictionary_t dict, pkgd, newpkgd; prop_array_t array; + const char *pkgname, *version, *desc; char *plist; int rv = 0; - assert(pkgname != NULL); - assert(version != NULL); - assert(desc != NULL); - plist = xbps_append_full_path(true, NULL, XBPS_REGPKGDB); if (plist == NULL) return EINVAL; + prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname); + prop_dictionary_get_cstring_nocopy(pkgrd, "version", &version); + prop_dictionary_get_cstring_nocopy(pkgrd, "short_desc", &desc); + dict = prop_dictionary_internalize_from_file(plist); if (dict == NULL) { - /* No packages registered yet. */ + /* + * No packages registered yet. Register package into + * the dictionary. + */ dict = prop_dictionary_create(); if (dict == NULL) { free(plist); @@ -254,36 +279,57 @@ xbps_register_pkg(prop_dictionary_t pkgrd, const char *pkgname, } } else { - /* Check if package is already registered. */ + /* + * Check if package is already registered and return + * an error if not updating. + */ pkgd = xbps_find_pkg_in_dict(dict, "packages", pkgname); - if (pkgd != NULL) { + if (pkgd != NULL && update == false) { rv = EEXIST; goto out; } - - pkgd = make_dict_from_pkg(pkgname, version, desc); array = prop_dictionary_get(dict, "packages"); if (array == NULL) { - prop_object_release(pkgd); rv = ENOENT; goto out; } - prop_dictionary_set_bool(pkgd, "automatic-install", - automatic); + newpkgd = make_dict_from_pkg(pkgname, version, desc); + prop_dictionary_set_bool(newpkgd, "automatic-install", + automatic); - if (pkgrd && xbps_pkg_has_rundeps(pkgrd)) { - rv = xbps_requiredby_pkg_add(array, pkgrd); + if (update && pkgrd && xbps_pkg_has_rundeps(pkgrd)) { + /* + * If updating a package, update the requiredby + * objects and set new version in pkg dictionary. + */ + rv = xbps_requiredby_pkg_add(array, pkgrd, true); if (rv != 0) { - prop_object_release(pkgd); + prop_object_release(newpkgd); goto out; } - } + prop_dictionary_set_cstring_nocopy(pkgd, + "version", version); - if (!xbps_add_obj_to_array(array, pkgd)) { - prop_object_release(pkgd); - rv = EINVAL; - goto out; + } else { + /* + * If installing a package, update the requiredby + * objects and add new pkg dictionary into the + * packages array. + */ + if (pkgrd && xbps_pkg_has_rundeps(pkgrd)) { + rv = xbps_requiredby_pkg_add(array, pkgrd, + false); + if (rv != 0) { + prop_object_release(newpkgd); + goto out; + } + } + if (!xbps_add_obj_to_array(array, newpkgd)) { + prop_object_release(newpkgd); + rv = EINVAL; + goto out; + } } } diff --git a/lib/requiredby.c b/lib/requiredby.c index f35a9a803a5..5f83300fa00 100644 --- a/lib/requiredby.c +++ b/lib/requiredby.c @@ -119,6 +119,44 @@ remove_pkg_from_reqby(prop_object_t obj, void *arg, bool *loop_done) return 0; } +static int +update_pkg_from_reqby(prop_dictionary_t pkgd, const char *reqname, + const char *reqpkg) +{ + prop_array_t reqby; + prop_object_iterator_t iter; + prop_object_t obj; + size_t idx = 0; + char *pkgname; + bool found = false; + + reqby = prop_dictionary_get(pkgd, "requiredby"); + if (reqby == NULL || prop_array_count(reqby) == 0) + return EINVAL; + + iter = prop_array_iterator(reqby); + if (iter == NULL) + return ENOMEM; + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + pkgname = xbps_get_pkg_name(prop_string_cstring_nocopy(obj)); + if (strcmp(reqname, pkgname) == 0) { + found = true; + break; + } + idx++; + } + prop_object_iterator_release(iter); + if (found == false) + return ENOENT; + + obj = prop_string_create_cstring(reqpkg); + if (!prop_array_set(reqby, idx, obj)) + return EINVAL; + + return 0; +} + int xbps_requiredby_pkg_remove(const char *pkgname) { @@ -150,7 +188,7 @@ xbps_requiredby_pkg_remove(const char *pkgname) } int -xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg) +xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg, bool update) { prop_array_t rdeps; prop_object_t obj, obj2; @@ -198,7 +236,11 @@ xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg) prop_dictionary_get_cstring_nocopy(obj2, "pkgname", &reqname); if (strcmp(rdepname, reqname) == 0) { - rv = add_pkg_into_reqby(obj2, fpkgn); + if (update) + rv = update_pkg_from_reqby(obj2, + pkgname, fpkgn); + else + rv = add_pkg_into_reqby(obj2, fpkgn); if (rv != 0) { free(rdepname); prop_object_iterator_release(iter2); diff --git a/lib/unpack.c b/lib/unpack.c index e5a53f03292..d0e58869ea3 100644 --- a/lib/unpack.c +++ b/lib/unpack.c @@ -35,11 +35,12 @@ #include -static int unpack_archive_init(prop_dictionary_t, const char *); -static int unpack_archive_fini(struct archive *, prop_dictionary_t); +static int unpack_archive_init(prop_dictionary_t, const char *, bool); +static int unpack_archive_fini(struct archive *, prop_dictionary_t, bool); int -xbps_unpack_binary_pkg(prop_dictionary_t repo, prop_dictionary_t pkg) +xbps_unpack_binary_pkg(prop_dictionary_t repo, prop_dictionary_t pkg, + bool update) { prop_string_t filename, repoloc, arch; char *binfile, *path; @@ -69,14 +70,14 @@ xbps_unpack_binary_pkg(prop_dictionary_t repo, prop_dictionary_t pkg) } free(path); - rv = unpack_archive_init(pkg, binfile); + rv = unpack_archive_init(pkg, binfile, update); free(binfile); return rv; } static int -unpack_archive_init(prop_dictionary_t pkg, const char *binfile) +unpack_archive_init(prop_dictionary_t pkg, const char *binfile, bool update) { struct archive *ar; int pkg_fd, rv; @@ -104,7 +105,7 @@ unpack_archive_init(prop_dictionary_t pkg, const char *binfile) return rv; } - rv = unpack_archive_fini(ar, pkg); + rv = unpack_archive_fini(ar, pkg, update); /* * If installation of package was successful, make sure the package * is really on storage (if possible). @@ -121,10 +122,10 @@ unpack_archive_init(prop_dictionary_t pkg, const char *binfile) /* * Flags for extracting files in binary packages. */ -#define EXTRACT_FLAGS ARCHIVE_EXTRACT_SECURE_NODOTDOT | \ - ARCHIVE_EXTRACT_SECURE_SYMLINKS | \ - ARCHIVE_EXTRACT_NO_OVERWRITE | \ +#define INSTALL_EFLAGS ARCHIVE_EXTRACT_NO_OVERWRITE | \ ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER +#define EXTRACT_FLAGS ARCHIVE_EXTRACT_SECURE_NODOTDOT | \ + ARCHIVE_EXTRACT_SECURE_SYMLINKS #define FEXTRACT_FLAGS ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | \ ARCHIVE_EXTRACT_TIME | EXTRACT_FLAGS @@ -133,7 +134,7 @@ unpack_archive_init(prop_dictionary_t pkg, const char *binfile) * the consumer. */ static int -unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg) +unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, bool update) { struct archive_entry *entry; size_t len; @@ -165,6 +166,9 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg) else lflags = EXTRACT_FLAGS; + if (update == false) + lflags |= INSTALL_EFLAGS; + /* * This length is '.%s/metadata/%s/INSTALL' + NULL. */