diff --git a/NEWS b/NEWS index 0da5e17e..26dc15fc 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,17 @@ xbps-0.38 (???): + * pkgdb-0.38 format: the pkgdb plist file now contains all pkg metadata objects + plus the pkgdb specific ones (automatic-install, install-date, metafile-sha256) + with the pkg files list being the exception. The pkgdb code will automatically + convert the pkgdb files to the new format the first time it's accesed. + + This effectively implements a two phase upgrade, the first time to upgrade the + pkgdb format and the second one to execute the real operation. + + The pkg metadata files stored in metadir (/var/db/xbps) now just contains its + pkg files list objects, everything else is stored in pkgdb. This allows libxbps + to speed up the process of checking for unmet shared libraries, among other things. + * libxbps: added support to check pkg shlib-{provides,requires} objects for all pkgs in transaction when installing or updating packages. This will help to avoid broken pkgs due to unmatched shlibs. diff --git a/bin/xbps-dgraph/main.c b/bin/xbps-dgraph/main.c index ad08a475..1b1c991a 100644 --- a/bin/xbps-dgraph/main.c +++ b/bin/xbps-dgraph/main.c @@ -508,7 +508,7 @@ main(int argc, char **argv) /* * Internalize the plist file of the target installed package. */ - plistd = xbps_pkgdb_get_pkg_metadata(&xh, argv[0]); + plistd = xbps_pkgdb_get_pkg(&xh, argv[0]); if (plistd == NULL) die("cannot internalize %s metadata file", argv[0]); diff --git a/bin/xbps-install/state_cb.c b/bin/xbps-install/state_cb.c index dffbf5e1..88f29259 100644 --- a/bin/xbps-install/state_cb.c +++ b/bin/xbps-install/state_cb.c @@ -59,6 +59,9 @@ state_cb(const struct xbps_state_cb_data *xscd, void *cbdata _unused) case XBPS_STATE_TRANS_CONFIGURE: printf("\n[*] Configuring unpacked packages\n"); break; + case XBPS_STATE_PKGDB: + printf("[*] pkgdb upgrade in progress, please wait...\n"); + break; case XBPS_STATE_REPOSYNC: printf("[*] Updating `%s' ...\n", xscd->arg); break; @@ -128,6 +131,10 @@ state_cb(const struct xbps_state_cb_data *xscd, void *cbdata _unused) xscd->xhp->rootdir); } break; + case XBPS_STATE_PKGDB_DONE: + printf("The pkgdb file has been upgraded successfully, please reexec " + "the command again.\n"); + break; case XBPS_STATE_REPO_KEY_IMPORT: printf("%s\n", xscd->desc); printf("Fingerprint: %s\n", xscd->arg); diff --git a/bin/xbps-install/transaction.c b/bin/xbps-install/transaction.c index 544345bf..7c5b69ab 100644 --- a/bin/xbps-install/transaction.c +++ b/bin/xbps-install/transaction.c @@ -281,9 +281,17 @@ exec_transaction(struct xbps_handle *xhp, int maxcols, bool yes, bool drun) if ((rv = xbps_transaction_prepare(xhp)) != 0) { if (rv == ENODEV) { array = xbps_dictionary_get(xhp->transd, "missing_deps"); - /* missing packages */ - print_array(array); - fprintf(stderr, "Transaction aborted due to missing packages.\n"); + if (xbps_array_count(array)) { + /* missing dependencies */ + print_array(array); + fprintf(stderr, "Transaction aborted due to unresolved dependencies.\n"); + } + array = xbps_dictionary_get(xhp->transd, "missing_shlibs"); + if (xbps_array_count(array)) { + /* missing shlibs */ + print_array(array); + fprintf(stderr, "Transaction aborted due to unresolved shlibs.\n"); + } goto out; } else if (rv == EAGAIN) { /* conflicts */ diff --git a/bin/xbps-pkgdb/Makefile b/bin/xbps-pkgdb/Makefile index 58e70739..1f44bf1e 100644 --- a/bin/xbps-pkgdb/Makefile +++ b/bin/xbps-pkgdb/Makefile @@ -5,6 +5,5 @@ BIN = xbps-pkgdb OBJS = main.o check.o check_pkg_files.o OBJS += check_pkg_rundeps.o OBJS += check_pkg_symlinks.o check_pkg_unneeded.o -OBJS += convert.o include $(TOPDIR)/mk/prog.mk diff --git a/bin/xbps-pkgdb/check.c b/bin/xbps-pkgdb/check.c index 47fc6b24..71deddb2 100644 --- a/bin/xbps-pkgdb/check.c +++ b/bin/xbps-pkgdb/check.c @@ -72,12 +72,12 @@ check_pkg_integrity(struct xbps_handle *xhp, xbps_dictionary_t pkgd, const char *pkgname) { - xbps_dictionary_t opkgd, propsd; + xbps_dictionary_t opkgd, filesd; const char *sha256; char *buf; int rv = 0; - propsd = opkgd = NULL; + filesd = opkgd = NULL; /* find real pkg by name */ opkgd = pkgd; @@ -89,17 +89,17 @@ check_pkg_integrity(struct xbps_handle *xhp, } } /* - * Check for props.plist metadata file. + * Check for pkg files metadata file. */ - buf = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname); - propsd = xbps_dictionary_internalize_from_file(buf); + buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); + filesd = xbps_dictionary_internalize_from_file(buf); free(buf); - if (propsd == NULL) { - xbps_error_printf("%s: unexistent metafile!\n", pkgname); + if (filesd == NULL) { + xbps_error_printf("%s: unexistent files metafile!\n", pkgname); return EINVAL; - } else if (xbps_dictionary_count(propsd) == 0) { + } else if (xbps_dictionary_count(filesd) == 0) { xbps_error_printf("%s: incomplete metadata file.\n", pkgname); - xbps_object_release(propsd); + xbps_object_release(filesd); return 1; } /* @@ -107,12 +107,12 @@ check_pkg_integrity(struct xbps_handle *xhp, */ xbps_dictionary_get_cstring_nocopy(opkgd, "metafile-sha256", &sha256); if (sha256 != NULL) { - buf = xbps_xasprintf("%s/.%s.plist", + buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); rv = xbps_file_hash_check(buf, sha256); free(buf); if (rv == ERANGE) { - xbps_object_release(propsd); + xbps_object_release(filesd); fprintf(stderr, "%s: metadata file has been " "modified!\n", pkgname); return 1; @@ -130,12 +130,12 @@ do { \ } while (0) /* Execute pkg checks */ - RUN_PKG_CHECK(xhp, files, propsd); - RUN_PKG_CHECK(xhp, symlinks, propsd); - RUN_PKG_CHECK(xhp, rundeps, propsd); + RUN_PKG_CHECK(xhp, files, filesd); + RUN_PKG_CHECK(xhp, symlinks, filesd); + RUN_PKG_CHECK(xhp, rundeps, opkgd); RUN_PKG_CHECK(xhp, unneeded, opkgd); - xbps_object_release(propsd); + xbps_object_release(filesd); #undef RUN_PKG_CHECK diff --git a/bin/xbps-pkgdb/convert.c b/bin/xbps-pkgdb/convert.c deleted file mode 100644 index 513c2754..00000000 --- a/bin/xbps-pkgdb/convert.c +++ /dev/null @@ -1,117 +0,0 @@ -/*- - * Copyright (c) 2013 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 -#include -#include - -#include -#include "defs.h" - -/* - * Convert pkgdb format to 0.21. - */ -static void -pkgdb_format_021(struct xbps_handle *xhp, const char *plist_new) -{ - xbps_array_t array, rdeps; - xbps_dictionary_t pkgdb, pkgd; - char *pkgname, *plist; - - plist = xbps_xasprintf("%s/pkgdb.plist", xhp->metadir); - if (access(plist, R_OK) == -1) { - if (errno == ENOENT) { - /* missing file, no conversion needed */ - free(plist); - return; - } - xbps_error_printf("cannot read %s: %s\n", - plist, strerror(errno)); - exit(EXIT_FAILURE); - } - - array = xbps_array_internalize_from_zfile(plist); - if (xbps_object_type(array) != XBPS_TYPE_ARRAY) { - xbps_error_printf("unknown object type for %s\n", - plist, strerror(errno)); - exit(EXIT_FAILURE); - } - - pkgdb = xbps_dictionary_create(); - assert(pkgdb); - - for (unsigned int i = 0; i < xbps_array_count(array); i++) { - pkgd = xbps_array_get(array, i); - xbps_dictionary_get_cstring(pkgd, "pkgname", &pkgname); - rdeps = xbps_dictionary_get(pkgd, "run_depends"); - /* remove unneeded objs */ - xbps_dictionary_remove(pkgd, "pkgname"); - xbps_dictionary_remove(pkgd, "version"); - if (xbps_array_count(rdeps) == 0) - xbps_dictionary_remove(pkgd, "run_depends"); - - xbps_dictionary_set(pkgdb, pkgname, pkgd); - free(pkgname); - } - - if (xbps_array_count(array) != xbps_dictionary_count(pkgdb)) { - xbps_error_printf("failed conversion! unmatched obj count " - "(got %zu, need %zu)\n", xbps_dictionary_count(pkgdb), - xbps_array_count(array)); - exit(EXIT_FAILURE); - } - - if (!xbps_dictionary_externalize_to_file(pkgdb, plist_new)) { - xbps_error_printf("failed to write %s: %s\n", - plist_new, strerror(errno)); - exit(EXIT_FAILURE); - } - - xbps_object_release(array); - xbps_object_release(pkgdb); - free(plist); - - printf("Conversion to 0.21 pkgdb format successfully\n"); -} - -void -convert_pkgdb_format(struct xbps_handle *xhp) -{ - char *plist; - - plist = xbps_xasprintf("%s/%s", xhp->metadir, XBPS_PKGDB); - if ((access(plist, R_OK) == -1) && (errno == ENOENT)) - pkgdb_format_021(xhp, plist); - - free(plist); -} diff --git a/bin/xbps-pkgdb/main.c b/bin/xbps-pkgdb/main.c index e42232fa..f1b67e9d 100644 --- a/bin/xbps-pkgdb/main.c +++ b/bin/xbps-pkgdb/main.c @@ -151,9 +151,10 @@ main(int argc, char **argv) fprintf(stderr, "failed to lock pkgdb: %s\n", strerror(rv)); exit(EXIT_FAILURE); } - if (update_format) - convert_pkgdb_format(&xh); - else if (instmode) { + if (update_format) { + /* nothing to do; xbps_pkgdb_lock() runs the conversion for us */ + goto out; + } else if (instmode) { if (argc == optind) { fprintf(stderr, "xbps-pkgdb: missing PKGNAME argument\n"); @@ -181,6 +182,7 @@ main(int argc, char **argv) } } +out: xbps_pkgdb_unlock(&xh); exit(rv ? EXIT_FAILURE : EXIT_SUCCESS); } diff --git a/bin/xbps-query/ownedby.c b/bin/xbps-query/ownedby.c index ec7b904b..592640aa 100644 --- a/bin/xbps-query/ownedby.c +++ b/bin/xbps-query/ownedby.c @@ -103,7 +103,7 @@ ownedby_pkgdb_cb(struct xbps_handle *xhp, xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - pkgmetad = xbps_pkgdb_get_pkg_metadata(xhp, pkgver); + pkgmetad = xbps_pkgdb_get_pkg_files(xhp, pkgver); assert(pkgmetad); files_keys = xbps_dictionary_all_keys(pkgmetad); diff --git a/bin/xbps-query/show-info-files.c b/bin/xbps-query/show-info-files.c index 5ce245ed..5b352db5 100644 --- a/bin/xbps-query/show-info-files.c +++ b/bin/xbps-query/show-info-files.c @@ -240,27 +240,12 @@ show_pkg_info_from_metadir(struct xbps_handle *xhp, const char *pkg, const char *option) { - xbps_array_t allkeys; - xbps_object_t obj, obj2; - xbps_dictionary_t d, pkgdb_d; - const char *key; + xbps_dictionary_t d; - pkgdb_d = xbps_pkgdb_get_pkg(xhp, pkg); - if (pkgdb_d == NULL) - return ENOENT; - - d = xbps_pkgdb_get_pkg_metadata(xhp, pkg); + d = xbps_pkgdb_get_pkg(xhp, pkg); if (d == NULL) return ENOENT; - allkeys = xbps_dictionary_all_keys(pkgdb_d); - for (unsigned int i = 0; i < xbps_array_count(allkeys); i++) { - obj = xbps_array_get(allkeys, i); - obj2 = xbps_dictionary_get_keysym(pkgdb_d, obj); - key = xbps_dictionary_keysym_cstring_nocopy(obj); - xbps_dictionary_set(d, key, obj2); - } - if (option == NULL) show_pkg_info(d); else @@ -275,7 +260,7 @@ show_pkg_files_from_metadir(struct xbps_handle *xhp, const char *pkg) xbps_dictionary_t d; int rv = 0; - d = xbps_pkgdb_get_pkg_metadata(xhp, pkg); + d = xbps_pkgdb_get_pkg_files(xhp, pkg); if (d == NULL) return ENOENT; diff --git a/include/xbps.h.in b/include/xbps.h.in index b93317b3..4a6c592e 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -48,7 +48,7 @@ * * This header documents the full API for the XBPS Library. */ -#define XBPS_API_VERSION "20140906" +#define XBPS_API_VERSION "20140909" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" @@ -128,7 +128,7 @@ * @def XBPS_PKGDB * Filename for the package database. */ -#define XBPS_PKGDB "pkgdb-0.21.plist" +#define XBPS_PKGDB "pkgdb-0.38.plist" /** * @def XBPS_PKGPROPS @@ -291,6 +291,8 @@ extern "C" { * - XBPS_STATE_SHOW_INSTALL_MSG: package must show a post-install message. * - XBPS_STATE_SHOW_REMOVE_MSG: package must show a pre-remove message. * - XBPS_STATE_UNPACK_FILE_PRESERVED: package unpack preserved a file. + * - XBPS_STATE_PKGDB: pkgdb upgrade in progress. + * - XBPS_STATE_PKGDB_DONE: pkgdb has been upgraded successfully. */ typedef enum xbps_state { XBPS_STATE_UNKNOWN = 0, @@ -333,7 +335,9 @@ typedef enum xbps_state { XBPS_STATE_INVALID_DEP, XBPS_STATE_SHOW_INSTALL_MSG, XBPS_STATE_SHOW_REMOVE_MSG, - XBPS_STATE_UNPACK_FILE_PRESERVED + XBPS_STATE_UNPACK_FILE_PRESERVED, + XBPS_STATE_PKGDB, + XBPS_STATE_PKGDB_DONE } xbps_state_t; /** @@ -517,7 +521,6 @@ struct xbps_handle { /** * @private */ - xbps_dictionary_t pkg_metad; xbps_dictionary_t pkgdb_revdeps; xbps_dictionary_t vpkgd; /** @@ -851,15 +854,15 @@ xbps_dictionary_t xbps_pkgdb_get_virtualpkg(struct xbps_handle *xhp, const char *pkg); /** - * Returns the package dictionary with all metadata info for \a pkg. + * Returns the package dictionary with all files for \a pkg. * * @param[in] xhp The pointer to the xbps_handle struct. * @param[in] pkg Package expression to match. * - * @return The matching package metadata dictionary, NULL otherwise. + * @return The matching package dictionary, NULL otherwise. */ -xbps_dictionary_t xbps_pkgdb_get_pkg_metadata(struct xbps_handle *xhp, - const char *pkg); +xbps_dictionary_t xbps_pkgdb_get_pkg_files(struct xbps_handle *xhp, + const char *pkg); /** * Returns a proplib array of strings with reverse dependencies diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index fbfc89a8..fdee4d1b 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -106,6 +106,7 @@ int HIDDEN dewey_match(const char *, const char *); */ int HIDDEN xbps_pkgdb_init(struct xbps_handle *); void HIDDEN xbps_pkgdb_release(struct xbps_handle *); +int HIDDEN xbps_pkgdb_conversion(struct xbps_handle *); /** * @private @@ -153,6 +154,7 @@ int HIDDEN xbps_cb_message(struct xbps_handle *, xbps_dictionary_t, const char * */ int HIDDEN xbps_entry_is_a_conf_file(xbps_dictionary_t, const char *); int HIDDEN xbps_entry_install_conf_file(struct xbps_handle *, + xbps_dictionary_t, xbps_dictionary_t, struct archive_entry *, const char *, diff --git a/lib/Makefile b/lib/Makefile index 796703a9..bb22f36b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -36,7 +36,7 @@ EXTOBJS = external/dewey.o external/fexec.o external/mkpath.o OBJS = package_configure.o package_config_files.o package_orphans.o OBJS += package_remove.o package_find_obsoletes.o package_state.o OBJS += package_unpack.o package_register.o package_script.o verifysig.o -OBJS += package_msg.o transaction_shlibs.o +OBJS += package_msg.o pkgdb_conversion.o transaction_shlibs.o OBJS += transaction_commit.o transaction_package_replace.o OBJS += transaction_dictionary.o transaction_sortdeps.o transaction_ops.o OBJS += transaction_revdeps.o pubkey2fp.o diff --git a/lib/package_config_files.c b/lib/package_config_files.c index 1b81931d..95832d7d 100644 --- a/lib/package_config_files.c +++ b/lib/package_config_files.c @@ -59,26 +59,26 @@ xbps_entry_is_a_conf_file(xbps_dictionary_t filesd, */ int HIDDEN xbps_entry_install_conf_file(struct xbps_handle *xhp, - xbps_dictionary_t filesd, + xbps_dictionary_t binpkg_filesd, + xbps_dictionary_t pkg_filesd, struct archive_entry *entry, const char *entry_pname, const char *pkgver, const char *pkgname) { - xbps_dictionary_t forigd; xbps_object_t obj, obj2; xbps_object_iterator_t iter, iter2; const char *version = NULL, *cffile, *sha256_new = NULL; char buf[PATH_MAX], *sha256_cur = NULL, *sha256_orig = NULL; int rv = 0; - assert(xbps_object_type(filesd) == XBPS_TYPE_DICTIONARY); + assert(xbps_object_type(binpkg_filesd) == XBPS_TYPE_DICTIONARY); assert(entry); assert(entry_pname); assert(pkgver); assert(pkgname); - iter = xbps_array_iter_from_dict(filesd, "conf_files"); + iter = xbps_array_iter_from_dict(binpkg_filesd, "conf_files"); if (iter == NULL) return -1; @@ -89,8 +89,7 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp, xbps_dbg_printf(xhp, "%s: processing conf_file %s\n", pkgver, entry_pname); - forigd = xbps_pkgdb_get_pkg_metadata(xhp, pkgname); - if (forigd == NULL) { + if (pkg_filesd == NULL) { /* * File exists on disk but it's not managed by the same package. * Install it as file.new-. @@ -107,7 +106,7 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp, goto out; } - iter2 = xbps_array_iter_from_dict(forigd, "conf_files"); + iter2 = xbps_array_iter_from_dict(pkg_filesd, "conf_files"); if (iter2 != NULL) { while ((obj2 = xbps_object_iterator_next(iter2))) { xbps_dictionary_get_cstring_nocopy(obj2, diff --git a/lib/package_configure.c b/lib/package_configure.c index ef841c5b..c1bdfb59 100644 --- a/lib/package_configure.c +++ b/lib/package_configure.c @@ -80,8 +80,8 @@ xbps_configure_pkg(struct xbps_handle *xhp, bool check_state, bool update) { - xbps_dictionary_t pkgd, pkgmetad; - char *pkgname, *plist; + xbps_dictionary_t pkgd; + char *pkgname; int rv = 0; pkg_state_t state = 0; @@ -125,23 +125,7 @@ xbps_configure_pkg(struct xbps_handle *xhp, xbps_set_cb_state(xhp, XBPS_STATE_CONFIGURE, 0, pkgver, NULL); - plist = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname); - free(pkgname); - - pkgmetad = xbps_dictionary_internalize_from_file(plist); - if (pkgmetad == NULL) { - rv = errno; - xbps_set_cb_state(xhp, XBPS_STATE_CONFIGURE_FAIL, - errno, pkgver, - "%s: [configure] cannot read metadata plist: %s", - pkgver, strerror(rv)); - return errno; - } - - free(plist); - assert(pkgmetad); - - rv = xbps_pkg_exec_script(xhp, pkgmetad, "install-script", "post", update); + rv = xbps_pkg_exec_script(xhp, pkgd, "install-script", "post", update); if (rv != 0) { xbps_set_cb_state(xhp, XBPS_STATE_CONFIGURE_FAIL, errno, pkgver, @@ -149,11 +133,6 @@ xbps_configure_pkg(struct xbps_handle *xhp, "the post ACTION: %s", pkgver, strerror(rv)); return rv; } - if (state == XBPS_PKG_STATE_INSTALLED) { - xbps_object_release(pkgmetad); - return rv; - } - rv = xbps_set_pkg_state_dictionary(pkgd, XBPS_PKG_STATE_INSTALLED); if (rv != 0) { xbps_set_cb_state(xhp, XBPS_STATE_CONFIGURE_FAIL, rv, @@ -165,10 +144,5 @@ xbps_configure_pkg(struct xbps_handle *xhp, xbps_set_cb_state(xhp, XBPS_STATE_CONFIGURE_DONE, 0, pkgver, NULL); /* show install-msg if exists */ - rv = xbps_cb_message(xhp, pkgmetad, "install-msg"); - - if (pkgmetad != NULL) - xbps_object_release(pkgmetad); - - return rv; + return xbps_cb_message(xhp, pkgd, "install-msg"); } diff --git a/lib/package_register.c b/lib/package_register.c index 19d66204..8cb86743 100644 --- a/lib/package_register.c +++ b/lib/package_register.c @@ -34,12 +34,10 @@ int HIDDEN xbps_register_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkgrd) { - xbps_dictionary_t pkgd; - xbps_array_t provides, rundeps; char outstr[64]; time_t t; struct tm *tmp; - const char *desc, *pkgver, *repo; + const char *pkgver; char *pkgname = NULL, *buf, *sha256; int rv = 0; bool autoinst = false; @@ -47,41 +45,17 @@ xbps_register_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkgrd) assert(xbps_object_type(pkgrd) == XBPS_TYPE_DICTIONARY); xbps_dictionary_get_cstring_nocopy(pkgrd, "pkgver", &pkgver); - xbps_dictionary_get_cstring_nocopy(pkgrd, "short_desc", &desc); - xbps_dictionary_get_cstring_nocopy(pkgrd, "repository", &repo); - xbps_dictionary_get_bool(pkgrd, "automatic-install", &autoinst); - provides = xbps_dictionary_get(pkgrd, "provides"); - rundeps = xbps_dictionary_get(pkgrd, "run_depends"); + pkgname = xbps_pkg_name(pkgver); + assert(pkgname); - assert(pkgver != NULL); - assert(desc != NULL); - - pkgd = xbps_pkgdb_get_pkg(xhp, pkgver); - if (pkgd == NULL) { - rv = ENOENT; - goto out; - } - if (!xbps_dictionary_set_cstring_nocopy(pkgd, - "pkgver", pkgver)) { - xbps_dbg_printf(xhp, "%s: invalid pkgver for %s\n", - __func__, pkgver); - rv = EINVAL; - goto out; - } - if (!xbps_dictionary_set_cstring_nocopy(pkgd, - "short_desc", desc)) { - xbps_dbg_printf(xhp, "%s: invalid short_desc for %s\n", - __func__, pkgver); - rv = EINVAL; - goto out; - } if (xhp->flags & XBPS_FLAG_INSTALL_AUTO) autoinst = true; - - if (!xbps_dictionary_set_bool(pkgd, - "automatic-install", autoinst)) { - xbps_dbg_printf(xhp, "%s: invalid autoinst for %s\n", - __func__, pkgver); + /* + * Set automatic-install to true, iff it was explicitly set; otherwise + * preserve its value. + */ + if (autoinst && !xbps_dictionary_set_bool(pkgrd, "automatic-install", true)) { + xbps_dbg_printf(xhp, "%s: invalid autoinst for %s\n", __func__, pkgver); rv = EINVAL; goto out; } @@ -101,50 +75,31 @@ xbps_register_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkgrd) rv = EINVAL; goto out; } - if (!xbps_dictionary_set_cstring(pkgd, "install-date", outstr)) { + if (!xbps_dictionary_set_cstring(pkgrd, "install-date", outstr)) { xbps_dbg_printf(xhp, "%s: install-date set failed!\n", pkgver); rv = EINVAL; goto out; } - - if (provides && !xbps_dictionary_set(pkgd, "provides", provides)) { - xbps_dbg_printf(xhp, "%s: failed to set provides for %s\n", - __func__, pkgver); - rv = EINVAL; - goto out; - } - if (rundeps && !xbps_dictionary_set(pkgd, "run_depends", rundeps)) { - xbps_dbg_printf(xhp, "%s: failed to set rundeps for %s\n", - __func__, pkgver); - rv = EINVAL; - goto out; - } - /* Save the repository origin which was used to install the pkg from */ - if (!xbps_dictionary_set_cstring(pkgd, "repository-origin", repo)) { - xbps_dbg_printf(xhp, "%s: repository-origin set failed!\n", pkgver); - rv = EINVAL; - goto out; - } - /* * Create a hash for the pkg's metafile. */ - pkgname = xbps_pkg_name(pkgver); - assert(pkgname); - buf = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname); + buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); sha256 = xbps_file_hash(buf); assert(sha256); - xbps_dictionary_set_cstring(pkgd, "metafile-sha256", sha256); + xbps_dictionary_set_cstring(pkgrd, "metafile-sha256", sha256); free(sha256); free(buf); /* * Remove unneeded objs from pkg dictionary. */ - xbps_dictionary_remove(pkgd, "remove-and-update"); - xbps_dictionary_remove(pkgd, "transaction"); - xbps_dictionary_remove(pkgd, "skip-obsoletes"); + xbps_dictionary_remove(pkgrd, "download"); + xbps_dictionary_remove(pkgrd, "remove-and-update"); + xbps_dictionary_remove(pkgrd, "transaction"); + xbps_dictionary_remove(pkgrd, "skip-obsoletes"); + xbps_dictionary_remove(pkgrd, "pkgname"); + xbps_dictionary_remove(pkgrd, "version"); - if (!xbps_dictionary_set(xhp->pkgdb, pkgname, pkgd)) { + if (!xbps_dictionary_set(xhp->pkgdb, pkgname, pkgrd)) { xbps_dbg_printf(xhp, "%s: failed to set pkgd for %s\n", __func__, pkgver); } diff --git a/lib/package_remove.c b/lib/package_remove.c index b57108fa..d34a7cbb 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -215,7 +215,7 @@ remove_pkg_files(struct xbps_handle *xhp, int HIDDEN xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update) { - xbps_dictionary_t pkgd = NULL; + xbps_dictionary_t pkgd = NULL, pkgfilesd = NULL; char *pkgname, metafile[PATH_MAX]; int rv = 0; pkg_state_t state = 0; @@ -226,7 +226,13 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update) pkgname = xbps_pkg_name(pkgver); assert(pkgname); - if ((rv = xbps_pkg_state_installed(xhp, pkgname, &state)) != 0) { + if ((pkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) { + rv = errno; + xbps_dbg_printf(xhp, "[remove] cannot find %s in pkgdb: %s\n", + pkgver, strerror(rv)); + goto out; + } + if ((rv = xbps_pkg_state_dictionary(pkgd, &state)) != 0) { xbps_dbg_printf(xhp, "[remove] cannot find %s in pkgdb: %s\n", pkgver, strerror(rv)); goto out; @@ -245,10 +251,10 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update) goto out; } - /* internalize pkg dictionary from metadir */ - snprintf(metafile, sizeof(metafile), "%s/.%s.plist", xhp->metadir, pkgname); - pkgd = xbps_dictionary_internalize_from_file(metafile); - if (pkgd == NULL) + /* internalize pkg files dictionary from metadir */ + snprintf(metafile, sizeof(metafile), "%s/.%s-files.plist", xhp->metadir, pkgname); + pkgfilesd = xbps_dictionary_internalize_from_file(metafile); + if (pkgfilesd == NULL) xbps_dbg_printf(xhp, "WARNING: metaplist for %s " "doesn't exist!\n", pkgver); @@ -258,70 +264,64 @@ xbps_remove_pkg(struct xbps_handle *xhp, const char *pkgver, bool update) /* * Run the pre remove action and show pre-remove message if exists. */ - if (pkgd) { - rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", - "pre", update); - if (rv != 0) { - xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL, - errno, pkgver, - "%s: [remove] REMOVE script failed to " - "execute pre ACTION: %s", - pkgver, strerror(rv)); - goto out; - } - /* show remove-msg if exists */ - rv = xbps_cb_message(xhp, pkgd, "remove-msg"); - if (rv != 0) - goto out; + rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "pre", update); + if (rv != 0) { + xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL, + errno, pkgver, + "%s: [remove] REMOVE script failed to " + "execute pre ACTION: %s", + pkgver, strerror(rv)); + goto out; } + /* show remove-msg if exists */ + if ((rv = xbps_cb_message(xhp, pkgd, "remove-msg")) != 0) + goto out; + /* * If updating a package, we just need to execute the current * pre-remove action target and we are done. Its files will be * overwritten later in unpack phase. */ if (update) { - if (pkgd) - xbps_object_release(pkgd); free(pkgname); return 0; } - if (pkgd) { + if (pkgfilesd) { /* * Do the removal in 2 phases: * 1- check if user has enough perms to remove all entries * 2- perform removal */ - if (check_remove_pkg_files(xhp, pkgd, pkgver)) { + if (check_remove_pkg_files(xhp, pkgfilesd, pkgver)) { rv = EPERM; goto out; } /* Remove regular files */ - if ((rv = remove_pkg_files(xhp, pkgd, "files", pkgver)) != 0) + if ((rv = remove_pkg_files(xhp, pkgfilesd, "files", pkgver)) != 0) goto out; /* Remove configuration files */ - if ((rv = remove_pkg_files(xhp, pkgd, "conf_files", pkgver)) != 0) + if ((rv = remove_pkg_files(xhp, pkgfilesd, "conf_files", pkgver)) != 0) goto out; /* Remove links */ - if ((rv = remove_pkg_files(xhp, pkgd, "links", pkgver)) != 0) + if ((rv = remove_pkg_files(xhp, pkgfilesd, "links", pkgver)) != 0) goto out; /* Remove dirs */ - if ((rv = remove_pkg_files(xhp, pkgd, "dirs", pkgver)) != 0) + if ((rv = remove_pkg_files(xhp, pkgfilesd, "dirs", pkgver)) != 0) goto out; - /* - * Execute the post REMOVE action if file exists and we aren't - * updating the package. - */ - rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "post", false); - if (rv != 0) { - xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL, - rv, pkgver, - "%s: [remove] REMOVE script failed to execute " - "post ACTION: %s", pkgver, strerror(rv)); - goto out; - } } - + /* + * Execute the post REMOVE action if file exists and we aren't + * updating the package. + */ + rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "post", false); + if (rv != 0) { + xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL, + rv, pkgver, + "%s: [remove] REMOVE script failed to execute " + "post ACTION: %s", pkgver, strerror(rv)); + goto out; + } /* * Set package state to "half-removed". */ @@ -339,16 +339,13 @@ purge: /* * Execute the purge REMOVE action if file exists. */ - if (pkgd) { - rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "purge", false); - if (rv != 0) { - xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL, - rv, pkgver, - "%s: REMOVE script failed to execute " - "purge ACTION: %s", pkgver, strerror(rv)); - goto out; - } - xbps_object_release(pkgd); + rv = xbps_pkg_exec_script(xhp, pkgd, "remove-script", "purge", false); + if (rv != 0) { + xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FAIL, + rv, pkgver, + "%s: REMOVE script failed to execute " + "purge ACTION: %s", pkgver, strerror(rv)); + goto out; } /* * Remove package metadata plist. diff --git a/lib/package_unpack.c b/lib/package_unpack.c index d62250d1..fdf6a936 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -78,79 +78,6 @@ find_pkg_symlink_target(xbps_dictionary_t d, const char *file) return tgt; } -static int -create_pkg_metaplist(struct xbps_handle *xhp, const char *pkgname, const char *pkgver, - xbps_dictionary_t propsd, xbps_dictionary_t filesd, - const void *instbuf, const size_t instbufsiz, - const void *rembuf, const size_t rembufsiz) -{ - xbps_array_t array; - xbps_dictionary_t pkg_metad; - xbps_data_t data; - char *buf; - int rv = 0; - - xbps_dictionary_make_immutable(propsd); - pkg_metad = xbps_dictionary_copy_mutable(propsd); - - /* Add objects from XBPS_PKGFILES */ - array = xbps_dictionary_get(filesd, "files"); - if (xbps_array_count(array)) - xbps_dictionary_set(pkg_metad, "files", array); - array = xbps_dictionary_get(filesd, "conf_files"); - if (xbps_array_count(array)) - xbps_dictionary_set(pkg_metad, "conf_files", array); - array = xbps_dictionary_get(filesd, "links"); - if (xbps_array_count(array)) - xbps_dictionary_set(pkg_metad, "links", array); - array = xbps_dictionary_get(filesd, "dirs"); - if (xbps_array_count(array)) - xbps_dictionary_set(pkg_metad, "dirs", array); - - /* Add install/remove scripts data objects */ - if (instbuf != NULL) { - data = xbps_data_create_data(instbuf, instbufsiz); - assert(data); - xbps_dictionary_set(pkg_metad, "install-script", data); - xbps_object_release(data); - } - if (rembuf != NULL) { - data = xbps_data_create_data(rembuf, rembufsiz); - assert(data); - xbps_dictionary_set(pkg_metad, "remove-script", data); - xbps_object_release(data); - } - /* Remove unneeded objs from transaction */ - xbps_dictionary_remove(pkg_metad, "remove-and-update"); - xbps_dictionary_remove(pkg_metad, "transaction"); - xbps_dictionary_remove(pkg_metad, "state"); - xbps_dictionary_remove(pkg_metad, "pkgname"); - xbps_dictionary_remove(pkg_metad, "version"); - - /* - * Externalize pkg dictionary to metadir. - */ - if (access(xhp->metadir, R_OK|X_OK) == -1) { - if (errno == ENOENT) { - xbps_mkpath(xhp->metadir, 0755); - } else { - return errno; - } - } - buf = xbps_xasprintf("%s/.%s.plist", XBPS_META_PATH, pkgname); - if (!xbps_dictionary_externalize_to_file(pkg_metad, buf)) { - rv = errno; - xbps_set_cb_state(xhp, XBPS_STATE_UNPACK_FAIL, - errno, pkgver, - "%s: [unpack] failed to write metadata file `%s': %s", - pkgver, buf, strerror(errno)); - } - free(buf); - xbps_object_release(pkg_metad); - - return rv; -} - static bool match_preserved_file(struct xbps_handle *xhp, const char *entry) { @@ -176,9 +103,10 @@ unpack_archive(struct xbps_handle *xhp, const char *fname, struct archive *ar) { - xbps_dictionary_t propsd, filesd, metapropsd; + xbps_dictionary_t binpkg_propsd, binpkg_filesd, pkg_filesd; xbps_array_t array, obsoletes; xbps_object_t obj; + xbps_data_t data; const struct stat *entry_statp; void *instbuf = NULL, *rembuf = NULL; struct stat st; @@ -193,7 +121,7 @@ unpack_archive(struct xbps_handle *xhp, bool skip_extract, force, xucd_stats; uid_t euid; - propsd = filesd = metapropsd = NULL; + binpkg_propsd = binpkg_filesd = pkg_filesd = NULL; force = preserve = update = conf_file = file_exists = false; skip_obsoletes = xucd_stats = false; ar_rv = rv = entry_type = flags = 0; @@ -258,19 +186,19 @@ unpack_archive(struct xbps_handle *xhp, goto out; } } else if (strcmp("./props.plist", entry_pname) == 0) { - propsd = xbps_archive_get_dictionary(ar, entry); - if (propsd == NULL) { + binpkg_propsd = xbps_archive_get_dictionary(ar, entry); + if (binpkg_propsd == NULL) { rv = EINVAL; goto out; } } else if (strcmp("./files.plist", entry_pname) == 0) { - filesd = xbps_archive_get_dictionary(ar, entry); - if (filesd == NULL) { + binpkg_filesd = xbps_archive_get_dictionary(ar, entry); + if (binpkg_filesd == NULL) { rv = EINVAL; goto out; } } - if (propsd && filesd) + if (binpkg_propsd && binpkg_filesd) break; } /* @@ -286,24 +214,40 @@ unpack_archive(struct xbps_handle *xhp, /* * Bail out if required metadata files are not in archive. */ - if (propsd == NULL || filesd == NULL) { + if (binpkg_propsd == NULL || binpkg_filesd == NULL) { xbps_set_cb_state(xhp, XBPS_STATE_UNPACK_FAIL, ENODEV, pkgver, "%s: [unpack] invalid binary package `%s'.", pkgver, fname); rv = ENODEV; goto out; } /* - * Create new metaplist file before unpacking any real file. + * Internalize current pkg metadata files plist. */ - metapropsd = xbps_pkgdb_get_pkg_metadata(xhp, pkgname); - rv = create_pkg_metaplist(xhp, pkgname, pkgver, - propsd, filesd, instbuf, instbufsiz, rembuf, rembufsiz); - if (rv != 0) { + pkg_filesd = xbps_pkgdb_get_pkg_files(xhp, pkgname); + + /* Add pkg install/remove scripts data objects into our dictionary */ + if (instbuf != NULL) { + data = xbps_data_create_data(instbuf, instbufsiz); + assert(data); + xbps_dictionary_set(pkg_repod, "install-script", data); + xbps_object_release(data); + } + if (rembuf != NULL) { + data = xbps_data_create_data(rembuf, rembufsiz); + assert(data); + xbps_dictionary_set(pkg_repod, "remove-script", data); + xbps_object_release(data); + } + buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); + if (!xbps_dictionary_externalize_to_file(binpkg_filesd, buf)) { + free(buf); + rv = errno; xbps_set_cb_state(xhp, XBPS_STATE_UNPACK_FAIL, rv, pkgver, - "%s: [unpack] failed to create metaplist file: %s", + "%s: [unpack] failed to externalize pkg metadata files: %s", pkgver, strerror(rv)); goto out; } + free(buf); /* * Execute INSTALL "pre" ACTION before unpacking files. */ @@ -350,14 +294,14 @@ unpack_archive(struct xbps_handle *xhp, * Compute total entries in progress data, if set. * total_entries = files + conf_files + links. */ - if (filesd && !xucd_stats) { - array = xbps_dictionary_get(filesd, "files"); + if (binpkg_filesd && !xucd_stats) { + array = xbps_dictionary_get(binpkg_filesd, "files"); xucd.entry_total_count += (ssize_t)xbps_array_count(array); - array = xbps_dictionary_get(filesd, "conf_files"); + array = xbps_dictionary_get(binpkg_filesd, "conf_files"); xucd.entry_total_count += (ssize_t)xbps_array_count(array); - array = xbps_dictionary_get(filesd, "links"); + array = xbps_dictionary_get(binpkg_filesd, "links"); xucd.entry_total_count += (ssize_t)xbps_array_count(array); xucd_stats = true; @@ -401,14 +345,14 @@ unpack_archive(struct xbps_handle *xhp, * "conf_files" array on its XBPS_PKGPROPS * dictionary. */ - if (xbps_entry_is_a_conf_file(filesd, buf)) { + if (xbps_entry_is_a_conf_file(binpkg_filesd, buf)) { conf_file = true; if (xhp->unpack_cb != NULL) xucd.entry_is_conf = true; rv = xbps_entry_install_conf_file(xhp, - filesd, entry, entry_pname, pkgver, - pkgname); + binpkg_filesd, pkg_filesd, entry, + entry_pname, pkgver, pkgname); if (rv == -1) { /* error */ goto out; @@ -421,7 +365,7 @@ unpack_archive(struct xbps_handle *xhp, rv = 0; } else { rv = xbps_file_hash_check_dictionary( - xhp, filesd, "files", buf); + xhp, binpkg_filesd, "files", buf); if (rv == -1) { /* error */ xbps_dbg_printf(xhp, @@ -456,7 +400,7 @@ unpack_archive(struct xbps_handle *xhp, p += strlen(xhp->rootdir); } else p = buf; - tgtlnk = find_pkg_symlink_target(filesd, + tgtlnk = find_pkg_symlink_target(binpkg_filesd, entry_pname); assert(tgtlnk); if (strncmp(tgtlnk, "./", 2) == 0) { @@ -573,10 +517,10 @@ unpack_archive(struct xbps_handle *xhp, * - Package reinstall. * - Package upgrade. */ - if (metapropsd == NULL || !xbps_dictionary_count(metapropsd)) + if (pkg_filesd == NULL || !xbps_dictionary_count(pkg_filesd)) goto out; - obsoletes = xbps_find_pkg_obsoletes(xhp, metapropsd, filesd); + obsoletes = xbps_find_pkg_obsoletes(xhp, pkg_filesd, binpkg_filesd); for (unsigned int i = 0; i < xbps_array_count(obsoletes); i++) { obj = xbps_array_get(obsoletes, i); file = xbps_string_cstring_nocopy(obj); @@ -593,13 +537,13 @@ unpack_archive(struct xbps_handle *xhp, 0, pkgver, "%s: removed obsolete entry: %s", pkgver, file); xbps_object_release(obj); } - xbps_object_release(metapropsd); + xbps_object_release(pkg_filesd); out: - if (xbps_object_type(filesd) == XBPS_TYPE_DICTIONARY) - xbps_object_release(filesd); - if (xbps_object_type(propsd) == XBPS_TYPE_DICTIONARY) - xbps_object_release(propsd); + if (xbps_object_type(binpkg_filesd) == XBPS_TYPE_DICTIONARY) + xbps_object_release(binpkg_filesd); + if (xbps_object_type(binpkg_propsd) == XBPS_TYPE_DICTIONARY) + xbps_object_release(binpkg_propsd); if (pkgname != NULL) free(pkgname); if (instbuf != NULL) @@ -670,6 +614,19 @@ xbps_unpack_binary_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod) pkgver, bpkg, strerror(rv)); goto out; } + /* + * Externalize pkg files dictionary to metadir. + */ + if (access(xhp->metadir, R_OK|X_OK) == -1) { + rv = errno; + if (rv != ENOENT) + goto out; + + if (xbps_mkpath(xhp->metadir, 0755) == -1) { + rv = errno; + goto out; + } + } /* * Extract archive files. */ @@ -682,7 +639,7 @@ xbps_unpack_binary_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod) /* * Set package state to unpacked. */ - if ((rv = xbps_set_pkg_state_installed(xhp, pkgver, + if ((rv = xbps_set_pkg_state_dictionary(pkg_repod, XBPS_PKG_STATE_UNPACKED)) != 0) { xbps_set_cb_state(xhp, XBPS_STATE_UNPACK_FAIL, rv, pkgver, diff --git a/lib/pkgdb.c b/lib/pkgdb.c index f9d33a4e..6466365a 100644 --- a/lib/pkgdb.c +++ b/lib/pkgdb.c @@ -124,11 +124,15 @@ xbps_pkgdb_init(struct xbps_handle *xhp) assert(xhp != NULL); - if (xhp->pkgdb != NULL) - return 0; if (xhp->pkgdb_plist == NULL) xhp->pkgdb_plist = xbps_xasprintf("%s/%s", xhp->metadir, XBPS_PKGDB); + if ((rv = xbps_pkgdb_conversion(xhp)) != 0) + return rv; + + if (xhp->pkgdb != NULL) + return 0; + if ((rv = xbps_pkgdb_update(xhp, false)) != 0) { if (rv != ENOENT) xbps_dbg_printf(xhp, "[pkgdb] cannot internalize " @@ -190,9 +194,6 @@ xbps_pkgdb_release(struct xbps_handle *xhp) /* write pkgdb to storage in case it was modified */ (void)xbps_pkgdb_update(xhp, true); - if (xbps_object_type(xhp->pkg_metad) == XBPS_TYPE_DICTIONARY) - xbps_object_release(xhp->pkg_metad); - xbps_object_release(xhp->pkgdb); xhp->pkgdb = NULL; xbps_dbg_printf(xhp, "[pkgdb] released ok.\n"); @@ -327,9 +328,9 @@ xbps_pkgdb_get_pkg_revdeps(struct xbps_handle *xhp, const char *pkg) } xbps_dictionary_t -xbps_pkgdb_get_pkg_metadata(struct xbps_handle *xhp, const char *pkg) +xbps_pkgdb_get_pkg_files(struct xbps_handle *xhp, const char *pkg) { - xbps_dictionary_t pkgd, pkg_metad; + xbps_dictionary_t pkgd, pkgfilesd; const char *pkgver; char *pkgname, *plist; @@ -344,27 +345,16 @@ xbps_pkgdb_get_pkg_metadata(struct xbps_handle *xhp, const char *pkg) pkgname = xbps_pkg_name(pkgver); assert(pkgname); - if ((pkg_metad = xbps_dictionary_get(xhp->pkg_metad, pkgname)) != NULL) { - free(pkgname); - return pkg_metad; - } - plist = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname); - pkg_metad = xbps_dictionary_internalize_from_file(plist); + plist = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); + free(pkgname); + pkgfilesd = xbps_dictionary_internalize_from_file(plist); free(plist); - if (pkg_metad == NULL) { + if (pkgfilesd == NULL) { xbps_dbg_printf(xhp, "[pkgdb] cannot read %s metadata: %s\n", pkgver, strerror(errno)); - free(pkgname); return NULL; } - if (xhp->pkg_metad == NULL) - xhp->pkg_metad = xbps_dictionary_create(); - - xbps_dictionary_set(xhp->pkg_metad, pkgname, pkg_metad); - xbps_object_release(pkg_metad); - free(pkgname); - - return pkg_metad; + return pkgfilesd; } diff --git a/lib/pkgdb_conversion.c b/lib/pkgdb_conversion.c new file mode 100644 index 00000000..3fa03879 --- /dev/null +++ b/lib/pkgdb_conversion.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2014 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 "xbps_api_impl.h" + +static int +pkgdb038(struct xbps_handle *xhp, const char *opkgdb_plist) +{ + xbps_dictionary_t pkgdb, opkgdb; + xbps_object_iterator_t iter; + xbps_object_t obj; + int rv = 0; + + /* + * The pkgdb-0.38.plist format contains all pkg metadata objects, + * except its files list. To avoid a broken conversion, the old + * pkg metadata plists are kept, and the converted ones are written + * to another path. + * + * - /pkgdb-0.38.plist + * - /.-files.plist + */ + opkgdb = xbps_dictionary_internalize_from_file(opkgdb_plist); + if (opkgdb == NULL) + return EINVAL; + + pkgdb = xbps_dictionary_create(); + assert(pkgdb); + /* + * Iterate over the old pkgdb dictionary and copy all pkg objects + * into the new pkgdb dictionary. + */ + iter = xbps_dictionary_iterator(opkgdb); + assert(iter); + + while ((obj = xbps_object_iterator_next(iter))) { + xbps_dictionary_t pkgd, pkgfilesd, pkgmetad; + xbps_object_iterator_t iter2; + xbps_object_t obj2; + const char *pkgname; + char *pkgmeta; + + pkgname = xbps_dictionary_keysym_cstring_nocopy(obj); + pkgd = xbps_dictionary_get_keysym(opkgdb, obj); + /* + * Copy old pkgdb objects to the new pkgdb. + */ + if (!xbps_dictionary_set(pkgdb, pkgname, pkgd)) { + xbps_dbg_printf(xhp, "%s: failed to copy %s pkgd " + "for pkgdb conversion\n", __func__, pkgname); + rv = EINVAL; + goto out; + } + /* + * Copy pkg metadata objs to the new pkgdb. + */ + pkgmeta = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname); + pkgmetad = xbps_dictionary_internalize_from_file(pkgmeta); + if (pkgmetad == NULL) { + rv = EINVAL; + xbps_dbg_printf(xhp, "%s: cannot open %s: %s\n", + __func__, pkgmeta, strerror(errno)); + goto out; + } + pkgfilesd = xbps_dictionary_create(); + assert(pkgfilesd); + + iter2 = xbps_dictionary_iterator(pkgmetad); + assert(iter2); + + while ((obj2 = xbps_object_iterator_next(iter2))) { + xbps_object_t curobj; + const char *key, *excluded[] = { + "conf_files", "dirs", "files", "links" + }; + bool skip = false; + + key = xbps_dictionary_keysym_cstring_nocopy(obj2); + curobj = xbps_dictionary_get_keysym(pkgmetad, obj2); + for (uint8_t i = 0; i < __arraycount(excluded); i++) { + if (strcmp(excluded[i], key) == 0) { + skip = true; + break; + } + } + if (skip) { + assert(xbps_object_type(curobj) == XBPS_TYPE_ARRAY); + if (xbps_array_count(curobj)) + xbps_dictionary_set(pkgfilesd, key, curobj); + + continue; + } + if (!xbps_dictionary_set(pkgd, key, curobj)) { + xbps_dbg_printf(xhp, "%s: failed to copy %s " + "pkgd for pkgdb conversion\n", pkgname, key); + xbps_object_iterator_release(iter2); + xbps_object_release(pkgmetad); + free(pkgmeta); + rv = EINVAL; + goto out; + } + } + xbps_object_iterator_release(iter2); + /* + * Externalize -files.plist if pkg contains any file. + */ + if (xbps_dictionary_count(pkgfilesd)) { + char *pkgfiles, *sha256; + + pkgfiles = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); + if (!xbps_dictionary_externalize_to_file(pkgfilesd, pkgfiles)) { + xbps_dbg_printf(xhp, "%s: failed to " + "externalize %s: %s\n", __func__, pkgfiles, strerror(errno)); + rv = EINVAL; + goto out; + } + xbps_dbg_printf(xhp, "%s: externalized %s successfully\n", __func__, pkgfiles); + /* + * Update SHA56 hash for the pkg files plist. + */ + sha256 = xbps_file_hash(pkgfiles); + assert(sha256); + xbps_dictionary_set_cstring(pkgd, "metafile-sha256", sha256); + free(sha256); + free(pkgfiles); + } + xbps_object_release(pkgfilesd); + xbps_object_release(pkgmetad); + free(pkgmeta); + } + /* + * Externalize the new pkgdb plist. + */ + if (!xbps_dictionary_externalize_to_file(pkgdb, xhp->pkgdb_plist)) { + xbps_dbg_printf(xhp, "%s: failed to externalize %s: " + "%s!\n", __func__, xhp->pkgdb_plist, strerror(errno)); + rv = EINVAL; + goto out; + } +out: + if (iter) + xbps_object_iterator_release(iter); + if (pkgdb) + xbps_object_release(pkgdb); + if (opkgdb) + xbps_object_release(opkgdb); + + return rv; +} + +int HIDDEN +xbps_pkgdb_conversion(struct xbps_handle *xhp) +{ + char *opkgdb = NULL; + int rv = 0; + + /* + * If pkgdb-0.38.plist exists there's nothing to do. + */ + if (xhp && xhp->pkgdb_plist && (access(xhp->pkgdb_plist, R_OK) == 0)) + return 0; + /* + * If pkgdb-0.21.plist does not exist there's nothing to do. + */ + opkgdb = xbps_xasprintf("%s/pkgdb-0.21.plist", xhp->metadir); + if (access(opkgdb, R_OK) == 0) { + /* + * Make the conversion and exit on success. It's just + * better to make the upgrade in two steps. + */ + xbps_set_cb_state(xhp, XBPS_STATE_PKGDB, 0, NULL, NULL); + if ((rv = pkgdb038(xhp, opkgdb)) == 0) { + xbps_set_cb_state(xhp, XBPS_STATE_PKGDB_DONE, 0, NULL, NULL); + xbps_end(xhp); + exit(EXIT_SUCCESS); + } + } + free(opkgdb); + + return rv; +} diff --git a/lib/repo_pkgdeps.c b/lib/repo_pkgdeps.c index 15fe2007..bad74389 100644 --- a/lib/repo_pkgdeps.c +++ b/lib/repo_pkgdeps.c @@ -49,7 +49,8 @@ store_dependency(struct xbps_handle *xhp, /* * Add required objects into package dep's dictionary. */ - if (!xbps_dictionary_set_bool(repo_pkgd, "automatic-install", true)) + if (!xbps_dictionary_get(repo_pkgd, "automatic-install") && + !xbps_dictionary_set_bool(repo_pkgd, "automatic-install", true)) return EINVAL; xbps_dictionary_get_cstring_nocopy(repo_pkgd, "pkgver", &pkgver); diff --git a/lib/transaction_dictionary.c b/lib/transaction_dictionary.c index e7ccde31..208f747f 100644 --- a/lib/transaction_dictionary.c +++ b/lib/transaction_dictionary.c @@ -121,7 +121,7 @@ compute_transaction_stats(struct xbps_handle *xhp) pkgname = xbps_pkg_name(pkgver); assert(pkgname); - pkg_metad = xbps_pkgdb_get_pkg_metadata(xhp, pkgname); + pkg_metad = xbps_pkgdb_get_pkg(xhp, pkgname); free(pkgname); if (pkg_metad == NULL) continue; @@ -220,6 +220,18 @@ xbps_transaction_init(struct xbps_handle *xhp) } xbps_object_release(array); + if ((array = xbps_array_create()) == NULL) { + xbps_object_release(xhp->transd); + xhp->transd = NULL; + return ENOMEM; + } + if (!xbps_dictionary_set(xhp->transd, "missing_shlibs", array)) { + xbps_object_release(xhp->transd); + xhp->transd = NULL; + return EINVAL; + } + xbps_object_release(array); + if ((array = xbps_array_create()) == NULL) { xbps_object_release(xhp->transd); xhp->transd = NULL; @@ -270,7 +282,6 @@ xbps_transaction_prepare(struct xbps_handle *xhp) array = xbps_dictionary_get(xhp->transd, "conflicts"); if (xbps_array_count(array)) return EAGAIN; - /* * Check for packages to be replaced. */ @@ -301,9 +312,10 @@ xbps_transaction_prepare(struct xbps_handle *xhp) return rv; } /* - * The missing deps and conflicts arrays are not necessary anymore. + * Remove now unneeded objects. */ xbps_dictionary_remove(xhp->transd, "unsorted"); + xbps_dictionary_remove(xhp->transd, "missing_shlibs"); xbps_dictionary_remove(xhp->transd, "missing_deps"); xbps_dictionary_remove(xhp->transd, "conflicts"); xbps_dictionary_make_immutable(xhp->transd); diff --git a/lib/transaction_ops.c b/lib/transaction_ops.c index 87191d44..d33466d6 100644 --- a/lib/transaction_ops.c +++ b/lib/transaction_ops.c @@ -136,8 +136,8 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall) * If pkg is already installed, respect its automatic-install * property. */ - xbps_dictionary_get_bool(pkg_pkgdb, "automatic-install", &autoinst); - xbps_dictionary_set_bool(pkg_repod, "automatic-install", autoinst); + if (xbps_dictionary_get_bool(pkg_pkgdb, "automatic-install", &autoinst)) + xbps_dictionary_set_bool(pkg_repod, "automatic-install", autoinst); } /* * Prepare transaction dictionary. diff --git a/lib/transaction_shlibs.c b/lib/transaction_shlibs.c index d573500a..624cb34a 100644 --- a/lib/transaction_shlibs.c +++ b/lib/transaction_shlibs.c @@ -57,18 +57,16 @@ shlib_in_pkgdb(struct xbps_handle *xhp, const char *pkgver, const char *shlib) while ((obj = xbps_object_iterator_next(iter))) { xbps_array_t shprovides; - xbps_dictionary_t pkgd, pkgmetad; + xbps_dictionary_t pkgd; const char *curpkgver; pkgd = xbps_dictionary_get_keysym(xhp->pkgdb, obj); - xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &curpkgver); - pkgmetad = xbps_pkgdb_get_pkg_metadata(xhp, curpkgver); - assert(pkgmetad); - shprovides = xbps_dictionary_get(pkgmetad, "shlib-provides"); + shprovides = xbps_dictionary_get(pkgd, "shlib-provides"); if (!shprovides) continue; if (xbps_match_string_in_array(shprovides, shlib)) { /* shlib matched */ + xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &curpkgver); xbps_dbg_printf(xhp, "[trans] %s requires `%s': " "matched by `%s' (pkgdb)\n", pkgver, shlib, curpkgver); found = true; @@ -109,9 +107,10 @@ shlib_in_transaction(struct xbps_handle *xhp, const char *pkgver, const char *sh bool HIDDEN xbps_transaction_shlibs(struct xbps_handle *xhp) { - xbps_array_t unsorted; + xbps_array_t unsorted, mshlibs; bool unmatched = false; + mshlibs = xbps_dictionary_get(xhp->transd, "missing_shlibs"); unsorted = xbps_dictionary_get(xhp->transd, "unsorted_deps"); for (unsigned int i = 0; i < xbps_array_count(unsorted); i++) { xbps_array_t shrequires; @@ -142,8 +141,13 @@ xbps_transaction_shlibs(struct xbps_handle *xhp) xbps_array_get_cstring_nocopy(shrequires, x, &shlib); if ((!shlib_in_pkgdb(xhp, pkgver, shlib)) && (!shlib_in_transaction(xhp, pkgver, shlib))) { - xbps_dbg_printf(xhp, "[trans] %s: needs `%s' " - "not provided by any pkg!\n", pkgver, shlib); + char *buf; + + buf = xbps_xasprintf("%s: needs `%s' shlib, not" + " provided by any pkg!", pkgver, shlib); + xbps_dbg_printf(xhp, "%s\n", buf); + xbps_array_add_cstring(mshlibs, buf); + free(buf); unmatched = true; } } diff --git a/tests/xbps/libxbps/find_pkg_orphans/Makefile b/tests/xbps/libxbps/find_pkg_orphans/Makefile index e986a44e..dac954f9 100644 --- a/tests/xbps/libxbps/find_pkg_orphans/Makefile +++ b/tests/xbps/libxbps/find_pkg_orphans/Makefile @@ -3,6 +3,6 @@ TOPDIR = ../../../.. TESTSSUBDIR = xbps/libxbps/find_pkg_orphans TEST = find_pkg_orphans_test -EXTRA_FILES = Kyuafile pkgdb-0.21.plist +EXTRA_FILES = Kyuafile pkgdb-0.38.plist include $(TOPDIR)/mk/test.mk diff --git a/tests/xbps/libxbps/find_pkg_orphans/pkgdb-0.21.plist b/tests/xbps/libxbps/find_pkg_orphans/pkgdb-0.38.plist similarity index 100% rename from tests/xbps/libxbps/find_pkg_orphans/pkgdb-0.21.plist rename to tests/xbps/libxbps/find_pkg_orphans/pkgdb-0.38.plist diff --git a/tests/xbps/libxbps/pkgdb/Makefile b/tests/xbps/libxbps/pkgdb/Makefile index c1eea1ac..99689128 100644 --- a/tests/xbps/libxbps/pkgdb/Makefile +++ b/tests/xbps/libxbps/pkgdb/Makefile @@ -3,6 +3,6 @@ TOPDIR = ../../../.. TESTSSUBDIR = xbps/libxbps/pkgdb TEST = pkgdb_test -EXTRA_FILES = Kyuafile pkgdb-0.21.plist +EXTRA_FILES = Kyuafile pkgdb-0.38.plist include $(TOPDIR)/mk/test.mk diff --git a/tests/xbps/libxbps/pkgdb/pkgdb-0.21.plist b/tests/xbps/libxbps/pkgdb/pkgdb-0.38.plist similarity index 100% rename from tests/xbps/libxbps/pkgdb/pkgdb-0.21.plist rename to tests/xbps/libxbps/pkgdb/pkgdb-0.38.plist diff --git a/tests/xbps/libxbps/shell/conf_files_test.sh b/tests/xbps/libxbps/shell/conf_files_test.sh index 738df44f..17886249 100644 --- a/tests/xbps/libxbps/shell/conf_files_test.sh +++ b/tests/xbps/libxbps/shell/conf_files_test.sh @@ -18,7 +18,7 @@ tc1_body() { rm -rf pkg_a xbps-rindex -a *.xbps atf_check_equal $? 0 - xbps-install -C null.conf -r rootdir --repository=$PWD -yv a + xbps-install -C null.conf -r rootdir --repository=$PWD -yvd a atf_check_equal $? 0 sed -e 's,fooblah,blahfoo,' -i rootdir/cf1.conf @@ -29,7 +29,7 @@ tc1_body() { xbps-rindex -a *.xbps rm -rf pkg_a atf_check_equal $? 0 - xbps-install -C null.conf -r rootdir --repository=$PWD -yuv + xbps-install -C null.conf -r rootdir --repository=$PWD -yuvd atf_check_equal $? 0 result="$(cat rootdir/cf1.conf)" rval=1 @@ -52,32 +52,34 @@ tc2_body() { cd repo mkdir pkg_a echo "fooblah" > pkg_a/cf1.conf - chmod 755 pkg_a/cf1.conf + chmod 644 pkg_a/cf1.conf xbps-create -A noarch -n a-0.1_1 -s "pkg a" --config-files "/cf1.conf" pkg_a atf_check_equal $? 0 rm -rf pkg_a xbps-rindex -a *.xbps atf_check_equal $? 0 - xbps-install -C null.conf -r rootdir --repository=$PWD -yv a + xbps-install -C null.conf -r rootdir --repository=$PWD -yvd a atf_check_equal $? 0 sed -e 's,fooblah,blahfoo,' -i rootdir/cf1.conf chmod 644 rootdir/cf1.conf mkdir pkg_a echo "bazbar" > pkg_a/cf1.conf - chmod 755 pkg_a/cf1.conf + chmod 644 pkg_a/cf1.conf xbps-create -A noarch -n a-0.2_1 -s "pkg a" --config-files "/cf1.conf" pkg_a atf_check_equal $? 0 xbps-rindex -a *.xbps rm -rf pkg_a atf_check_equal $? 0 - xbps-install -C null.conf -r rootdir --repository=$PWD -yuv + xbps-install -C null.conf -r rootdir --repository=$PWD -yuvd atf_check_equal $? 0 result="$(cat rootdir/cf1.conf)" rval=1 if [ "${result}" = "blahfoo" ]; then rval=0 fi + echo "result: ${result}" + echo "expected: blahfoo" atf_check_equal $rval 0 rval=1 if [ -s rootdir/cf1.conf.new-0.2_1 ]; then @@ -99,26 +101,26 @@ tc3_body() { cd repo mkdir pkg_a echo "fooblah" > pkg_a/cf1.conf - chmod 755 pkg_a/cf1.conf + chmod 644 pkg_a/cf1.conf xbps-create -A noarch -n a-0.1_1 -s "pkg a" --config-files "/cf1.conf" pkg_a atf_check_equal $? 0 rm -rf pkg_a xbps-rindex -a *.xbps atf_check_equal $? 0 - xbps-install -C null.conf -r rootdir --repository=$PWD -yv a + xbps-install -C null.conf -r rootdir --repository=$PWD -yvd a atf_check_equal $? 0 sed -e 's,fooblah,blahfoo,' -i rootdir/cf1.conf chmod 644 rootdir/cf1.conf mkdir pkg_a echo "fooblah" > pkg_a/cf1.conf - chmod 755 pkg_a/cf1.conf + chmod 644 pkg_a/cf1.conf xbps-create -A noarch -n a-0.2_1 -s "pkg a" --config-files "/cf1.conf" pkg_a atf_check_equal $? 0 xbps-rindex -a *.xbps rm -rf pkg_a atf_check_equal $? 0 - xbps-install -C null.conf -r rootdir --repository=$PWD -yuv + xbps-install -C null.conf -r rootdir --repository=$PWD -yuvd atf_check_equal $? 0 result="$(cat rootdir/cf1.conf)" rval=1 @@ -141,7 +143,7 @@ tc4_body() { cd repo mkdir -p pkg_a/etc echo "fooblah" > pkg_a/etc/cf1.conf - chmod 755 pkg_a/etc/cf1.conf + chmod 644 pkg_a/etc/cf1.conf xbps-create -A noarch -n a-0.1_1 -s "pkg a" --config-files "/etc/cf1.conf" pkg_a atf_check_equal $? 0 rm -rf pkg_a diff --git a/tests/xbps/libxbps/shell/installmode_test.sh b/tests/xbps/libxbps/shell/installmode_test.sh index b235fde6..fc21cd4c 100644 --- a/tests/xbps/libxbps/shell/installmode_test.sh +++ b/tests/xbps/libxbps/shell/installmode_test.sh @@ -19,7 +19,7 @@ instmode_update_body() { atf_check_equal $? 0 cd .. - xbps-install -r root -C null.conf --repository=$PWD/some_repo -A -y A-1.0_1 + xbps-install -r root -C null.conf --repository=$PWD/some_repo -Ayd A-1.0_1 atf_check_equal $? 0 cd some_repo @@ -29,7 +29,7 @@ instmode_update_body() { atf_check_equal $? 0 cd .. - xbps-install -r root -C null.conf --repository=$PWD/some_repo -yu + xbps-install -r root -C null.conf --repository=$PWD/some_repo -yud atf_check_equal $? 0 out=$(xbps-query -r root --property=automatic-install A) atf_check_equal $out yes