From 06c9891ae377b35cf5741ea90a964bcad9fa404c Mon Sep 17 00:00:00 2001 From: Juan RP Date: Fri, 21 Feb 2020 09:08:22 +0100 Subject: [PATCH] xbps_transaction_*: multiple performance improvements (v2). This commit implements multiple performance improvements to the transaction code: - Don't process xbps_pkg_name() N times each time we access its package dictionary (via pkgdb or rpool), just do it once at xbps_pkgdb_init() time. At pkgdb init time, it just creates a property in pkgdb, "pkgname". At rpool time, each time a package is accessed, the "pkgname" string property is added. - The package transaction dictionary contains the "transaction" object to know what's the pkg type. This has been changed to an uint8, this simplifies the logic and it's faster than checking a string object. See xbps_trans_type_t and xbps_transaction_pkg_type(). - Fixed the issue that was marked with XXX in transaction shlibs checking code. This has been fixed and improved and resources are now just freed as expected. - Simplified random code all over the place, avoiding unnecessary allocations or operations. - Rename some transaction files to have a better description. This is my first rototill to the code in 2020. --- bin/xbps-install/state_cb.c | 2 +- bin/xbps-install/transaction.c | 93 ++++--- bin/xbps-install/util.c | 62 ++--- include/xbps.h.in | 129 ++++++---- include/xbps_api_impl.h | 30 +-- lib/Makefile | 14 +- lib/package_alternatives.c | 14 +- lib/package_fulldeptree.c | 11 +- lib/package_orphans.c | 8 +- lib/package_register.c | 10 +- lib/package_unpack.c | 17 +- lib/pkgdb.c | 94 +++++--- lib/plist.c | 25 +- lib/plist_find.c | 82 +++---- lib/repo.c | 69 ++++-- ...flicts.c => transaction_check_conflicts.c} | 141 ++++++----- ...replace.c => transaction_check_replaces.c} | 117 +++++---- ..._revdeps.c => transaction_check_revdeps.c} | 111 +++++---- ...on_shlibs.c => transaction_check_shlibs.c} | 47 ++-- lib/transaction_commit.c | 38 +-- lib/transaction_fetch.c | 20 +- lib/transaction_files.c | 50 ++-- lib/transaction_ops.c | 228 +++++++++++------- ...{repo_pkgdeps.c => transaction_pkg_deps.c} | 133 +++++----- lib/transaction_prepare.c | 108 +++++---- lib/transaction_store.c | 41 ++-- tests/xbps/libxbps/shell/hold_test.sh | 4 - tests/xbps/libxbps/shell/update_hold_test.sh | 4 - 28 files changed, 960 insertions(+), 742 deletions(-) rename lib/{transaction_conflicts.c => transaction_check_conflicts.c} (64%) rename lib/{transaction_package_replace.c => transaction_check_replaces.c} (62%) rename lib/{transaction_revdeps.c => transaction_check_revdeps.c} (74%) rename lib/{transaction_shlibs.c => transaction_check_shlibs.c} (85%) rename lib/{repo_pkgdeps.c => transaction_pkg_deps.c} (79%) diff --git a/bin/xbps-install/state_cb.c b/bin/xbps-install/state_cb.c index 3c00b001..a0a2f625 100644 --- a/bin/xbps-install/state_cb.c +++ b/bin/xbps-install/state_cb.c @@ -66,7 +66,7 @@ state_cb(const struct xbps_state_cb_data *xscd, void *cbdata UNUSED) printf("[*] pkgdb upgrade in progress, please wait...\n"); break; case XBPS_STATE_REPOSYNC: - printf("[*] Updating `%s' ...\n", xscd->arg); + printf("[*] Updating repository `%s' ...\n", xscd->arg); break; case XBPS_STATE_TRANS_ADDPKG: if (xscd->xhp->flags & XBPS_FLAG_VERBOSE) diff --git a/bin/xbps-install/transaction.c b/bin/xbps-install/transaction.c index a4878631..d47ed1e4 100644 --- a/bin/xbps-install/transaction.c +++ b/bin/xbps-install/transaction.c @@ -47,6 +47,38 @@ print_array(xbps_array_t a) } } +static const char * +ttype2str(xbps_dictionary_t pkg_repod) +{ + uint8_t r; + + assert(pkg_repod); + + if (!xbps_dictionary_get_uint8(pkg_repod, "transaction", &r)) + return NULL; + + switch (r) { + case XBPS_TRANS_INSTALL: + return "install"; + case XBPS_TRANS_REINSTALL: + return "reinstall"; + case XBPS_TRANS_UPDATE: + return "update"; + case XBPS_TRANS_REMOVE: + return "remove"; + case XBPS_TRANS_CONFIGURE: + return "configure"; + case XBPS_TRANS_HOLD: + return "hold"; + case XBPS_TRANS_DOWNLOAD: + return "download"; + default: + return "unknown"; + } + + return NULL; +} + static void show_actions(xbps_object_iterator_t iter) { @@ -54,13 +86,12 @@ show_actions(xbps_object_iterator_t iter) const char *repoloc, *trans, *pkgver, *arch; uint64_t isize, dsize; - repoloc = trans = pkgver = arch = NULL; - isize = dsize = 0; - while ((obj = xbps_object_iterator_next(iter)) != NULL) { - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &trans); + repoloc = trans = pkgver = arch = NULL; + isize = dsize = 0; + xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - printf("%s %s", pkgver, trans); + printf("%s %s", pkgver, ttype2str(obj)); xbps_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); xbps_dictionary_get_cstring_nocopy(obj, "architecture", &arch); if (repoloc && arch) @@ -77,28 +108,25 @@ show_actions(xbps_object_iterator_t iter) } static void -show_package_list(struct transaction *trans, const char *match, int cols) +show_package_list(struct transaction *trans, xbps_trans_type_t ttype, int cols) { + xbps_dictionary_t ipkgd; xbps_object_t obj; + xbps_trans_type_t tt; + const char *pkgver, *pkgname, *ipkgver, *version, *iversion; + char *buf = NULL; while ((obj = xbps_object_iterator_next(trans->iter)) != NULL) { - const char *pkgver, *tract; - char *buf = NULL; bool dload = false; + pkgver = ipkgver = version = iversion = NULL; xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract); + xbps_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); xbps_dictionary_get_bool(obj, "download", &dload); + tt = xbps_transaction_pkg_type(obj); - if (match && strcmp(tract, "update") == 0) { - xbps_dictionary_t ipkgd; - const char *ipkgver, *iversion, *version; - char pkgname[XBPS_NAME_SIZE]; - + if (tt == XBPS_TRANS_UPDATE) { /* get installed pkgver */ - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); - } ipkgd = xbps_pkgdb_get_pkg(trans->xhp, pkgname); assert(ipkgd); xbps_dictionary_get_cstring_nocopy(ipkgd, "pkgver", &ipkgver); @@ -106,7 +134,7 @@ show_package_list(struct transaction *trans, const char *match, int cols) iversion = xbps_pkg_version(ipkgver); buf = xbps_xasprintf("%s (%s -> %s)", pkgname, iversion, version); } - if ((match && (strcmp(match, tract) == 0)) || (!match && dload)) { + if ((ttype && (ttype == tt)) || (!ttype && dload)) { if (buf) { print_package_line(buf, cols, false); free(buf); @@ -135,23 +163,15 @@ show_transaction_sizes(struct transaction *trans, int cols) if (trans->dl_pkgcnt) { printf("%u package%s will be downloaded:\n", trans->dl_pkgcnt, trans->dl_pkgcnt == 1 ? "" : "s"); - show_package_list(trans, NULL, cols); + show_package_list(trans, XBPS_TRANS_DOWNLOAD, cols); printf("\n"); } - if (trans->xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { - trans->inst_pkgcnt = 0; - trans->up_pkgcnt = 0; - trans->cf_pkgcnt = 0; - trans->rm_pkgcnt = 0; - goto out; - } - xbps_dictionary_get_uint32(trans->d, "total-install-pkgs", &trans->inst_pkgcnt); if (trans->inst_pkgcnt) { printf("%u package%s will be installed:\n", trans->inst_pkgcnt, trans->inst_pkgcnt == 1 ? "" : "s"); - show_package_list(trans, "install", cols); + show_package_list(trans, XBPS_TRANS_INSTALL, cols); printf("\n"); } xbps_dictionary_get_uint32(trans->d, "total-update-pkgs", @@ -159,7 +179,7 @@ show_transaction_sizes(struct transaction *trans, int cols) if (trans->up_pkgcnt) { printf("%u package%s will be updated:\n", trans->up_pkgcnt, trans->up_pkgcnt == 1 ? "" : "s"); - show_package_list(trans, "update", cols); + show_package_list(trans, XBPS_TRANS_UPDATE, cols); printf("\n"); } xbps_dictionary_get_uint32(trans->d, "total-configure-pkgs", @@ -167,7 +187,7 @@ show_transaction_sizes(struct transaction *trans, int cols) if (trans->cf_pkgcnt) { printf("%u package%s will be configured:\n", trans->cf_pkgcnt, trans->cf_pkgcnt == 1 ? "" : "s"); - show_package_list(trans, "configure", cols); + show_package_list(trans, XBPS_TRANS_CONFIGURE, cols); printf("\n"); } xbps_dictionary_get_uint32(trans->d, "total-remove-pkgs", @@ -175,11 +195,10 @@ show_transaction_sizes(struct transaction *trans, int cols) if (trans->rm_pkgcnt) { printf("%u package%s will be removed:\n", trans->rm_pkgcnt, trans->rm_pkgcnt == 1 ? "" : "s"); - show_package_list(trans, "remove", cols); + show_package_list(trans, XBPS_TRANS_REMOVE, cols); printf("\n"); } } -out: /* * Show total download/installed/removed size for all required packages. */ @@ -232,18 +251,16 @@ static bool all_pkgs_on_hold(struct transaction *trans) { xbps_object_t obj; - const char *action = NULL; + xbps_trans_type_t ttype; bool all_on_hold = true; while ((obj = xbps_object_iterator_next(trans->iter)) != NULL) { - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &action); - if (strcmp(action, "hold")) { + ttype = xbps_transaction_pkg_type(obj); + if (ttype != XBPS_TRANS_HOLD) { all_on_hold = false; - goto out; + break; } } - -out: xbps_object_iterator_reset(trans->iter); return all_on_hold; } diff --git a/bin/xbps-install/util.c b/bin/xbps-install/util.c index bb48d115..088c0e05 100644 --- a/bin/xbps-install/util.c +++ b/bin/xbps-install/util.c @@ -81,15 +81,12 @@ static unsigned int find_longest_pkgname(struct transaction *trans) { xbps_object_t obj; - const char *pkgver; - char pkgname[XBPS_NAME_SIZE]; + const char *pkgname; unsigned int len = 0, max = 0; while ((obj = xbps_object_iterator_next(trans->iter)) != NULL) { - xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); - } + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname)) + continue; len = strlen(pkgname); if (max == 0 || len > max) max = len; @@ -101,9 +98,12 @@ find_longest_pkgname(struct transaction *trans) bool print_trans_colmode(struct transaction *trans, int cols) { + xbps_dictionary_t ipkgd; xbps_object_t obj; - uint64_t dlsize = 0; + xbps_trans_type_t ttype; + const char *pkgver, *pkgname, *ipkgver, *ver, *iver, *tract; char size[8]; + uint64_t dlsize = 0; unsigned int x, blen, pnamelen; int hdrlen; @@ -123,43 +123,49 @@ print_trans_colmode(struct transaction *trans, int cols) printf("Action Version New version Download size\n"); while ((obj = xbps_object_iterator_next(trans->iter)) != NULL) { - xbps_dictionary_t ipkgd; - const char *pkgver, *ipkgver, *ver, *iver, *tract; - char pkgname[XBPS_NAME_SIZE]; bool dload = false; - ver = iver = NULL; - + pkgver = pkgname = ipkgver = ver = iver = NULL; xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract); + xbps_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); xbps_dictionary_get_uint64(obj, "filename-size", &dlsize); xbps_dictionary_get_bool(obj, "download", &dload); - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); - } + ttype = xbps_transaction_pkg_type(obj); + tract = "unknown"; if (trans->xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { tract = "download"; } - if (strcmp(tract, "install") == 0) { + if (ttype == XBPS_TRANS_INSTALL) { trans->inst_pkgcnt++; - } else if (strcmp(tract, "update") == 0) { + tract = "install"; + } else if (ttype == XBPS_TRANS_REINSTALL) { + trans->inst_pkgcnt++; + tract = "reinstall"; + } else if (ttype == XBPS_TRANS_UPDATE) { trans->up_pkgcnt++; - } else if (strcmp(tract, "remove") == 0) { + tract = "update"; + } else if (ttype == XBPS_TRANS_REMOVE) { trans->rm_pkgcnt++; - } else if (strcmp(tract, "configure") == 0) { + tract = "remove"; + } else if (ttype == XBPS_TRANS_CONFIGURE) { trans->cf_pkgcnt++; - } - ipkgd = xbps_pkgdb_get_pkg(trans->xhp, pkgname); - - if (trans->xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { - ipkgd = NULL; + tract = "configure"; + } else if (ttype == XBPS_TRANS_HOLD) { + tract = "hold"; + } else if (ttype == XBPS_TRANS_DOWNLOAD) { + tract = "download"; } if (dload) { trans->dl_pkgcnt++; } + + ipkgd = xbps_pkgdb_get_pkg(trans->xhp, pkgname); + if (trans->xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { + ipkgd = NULL; + } if (ipkgd) { xbps_dictionary_get_cstring_nocopy(ipkgd, "pkgver", &ipkgver); iver = xbps_pkg_version(ipkgver); @@ -167,10 +173,8 @@ print_trans_colmode(struct transaction *trans, int cols) ver = xbps_pkg_version(pkgver); if (iver) { int rv = xbps_cmpver(iver, ver); - if (rv == 1 && strcmp(tract, "hold")) + if (rv == 1 && ttype != XBPS_TRANS_HOLD) tract = "downgrade"; - else if (rv == 0 && strcmp(tract, "remove")) - tract = "reinstall"; } /* print pkgname and some blanks */ blen = pnamelen - strlen(pkgname); @@ -192,7 +196,7 @@ print_trans_colmode(struct transaction *trans, int cols) for (x = strlen(iver); x < 17; x++) printf(" "); - if (strcmp(tract, "remove") == 0) { + if (ttype == XBPS_TRANS_REMOVE) { ver = "-"; } if (dload) diff --git a/include/xbps.h.in b/include/xbps.h.in index 849142c9..a8024a2b 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2019 Juan Romero Pardines + * Copyright (c) 2008-2020 Juan Romero Pardines * Copyright (c) 2014-2019 Enno Boland * Copyright (c) 2016-2019 Duncan Overbruck * All rights reserved. @@ -51,7 +51,7 @@ * * This header documents the full API for the XBPS Library. */ -#define XBPS_API_VERSION "20200210" +#define XBPS_API_VERSION "20200221" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" @@ -238,7 +238,7 @@ * installation. * Must be set through the xbps_handle::flags member. */ -#define XBPS_FLAG_KEEP_CONFIG 0x00010000 +#define XBPS_FLAG_KEEP_CONFIG 0x00010000 /** * @def XBPS_FETCH_CACHECONN @@ -285,10 +285,8 @@ extern "C" { * - XBPS_STATE_UKKNOWN: state hasn't been prepared or unknown error. * - XBPS_STATE_TRANS_DOWNLOAD: transaction is downloading binary packages. * - XBPS_STATE_TRANS_VERIFY: transaction is verifying binary package integrity. - * - XBPS_STATE_TRANS_RUN: transaction is performing operations: - * install, update, remove and replace. - * - XBPS_STATE_TRANS_CONFIGURE: transaction is configuring all - * unpacked packages. + * - XBPS_STATE_TRANS_RUN: transaction is performing operations: install, update, remove, replace. + * - XBPS_STATE_TRANS_CONFIGURE: transaction is configuring all unpacked packages. * - XBPS_STATE_TRANS_FAIL: transaction has failed. * - XBPS_STATE_DOWNLOAD: a binary package is being downloaded. * - XBPS_STATE_VERIFY: a binary package is being verified. @@ -305,19 +303,15 @@ extern "C" { * - XBPS_STATE_CONFIGURE: a package is being configured. * - XBPS_STATE_CONFIGURE_DONE: a package has been configured successfully. * - XBPS_STATE_CONFIG_FILE: a package configuration file is being processed. - * - XBPS_STATE_REPOSYNC: a remote repository's package index is being - * synchronized. + * - XBPS_STATE_REPOSYNC: a remote repository's package index is being synchronized. * - XBPS_STATE_VERIFY_FAIL: binary package integrity has failed. * - XBPS_STATE_DOWNLOAD_FAIL: binary package download has failed. * - XBPS_STATE_REMOVE_FAIL: a package removal has failed. * - XBPS_STATE_REMOVE_FILE_FAIL: a package file removal has failed. - * - XBPS_STATE_REMOVE_FILE_HASH_FAIL: a package file removal due to - * its hash has failed. - * - XBPS_STATE_REMOVE_FILE_OBSOLETE_FAIL: an obsolete package file - * removal has failed. + * - XBPS_STATE_REMOVE_FILE_HASH_FAIL: a package file removal has failed due to hash. + * - XBPS_STATE_REMOVE_FILE_OBSOLETE_FAIL: an obsolete package file removal has failed. * - XBPS_STATE_CONFIGURE_FAIL: package configure has failed. - * - XBPS_STATE_CONFIG_FILE_FAIL: package configuration file operation - * has failed. + * - XBPS_STATE_CONFIG_FILE_FAIL: package configuration file operation has failed. * - XBPS_STATE_UPDATE_FAIL: package update has failed. * - XBPS_STATE_UNPACK_FAIL: package unpack has failed. * - XBPS_STATE_REPOSYNC_FAIL: syncing remote repositories has failed. @@ -680,13 +674,9 @@ struct xbps_handle { /** * @var flags * - * Flags to be set globally by ORing them, possible values: - * - XBPS_FLAG_VERBOSE - * - XBPS_FLAG_FORCE_CONFIGURE - * - XBPS_FLAG_FORCE_REMOVE_FILES - * - XBPS_FLAG_DEBUG - * - XBPS_FLAG_INSTALL_AUTO - * - XBPS_FLAG_DISABLE_SYSLOG + * Flags to be set globally by ORing them, possible value: + * + * - XBPS_FLAG_* (see above) */ int flags; }; @@ -1118,8 +1108,7 @@ bool xbps_match_virtual_pkg_in_dict(xbps_dictionary_t pkgd, const char *str); * * @return True if \a any virtualpkg has been matched, false otherwise. */ -bool xbps_match_any_virtualpkg_in_rundeps(xbps_array_t rundeps, - xbps_array_t provides); +bool xbps_match_any_virtualpkg_in_rundeps(xbps_array_t rundeps, xbps_array_t provides); /** * Match a package name in the specified array of strings. @@ -1182,8 +1171,7 @@ bool xbps_match_string_in_array(xbps_array_t array, const char *val); * @return A proplib object iterator on success, NULL otherwise and * errno is set appropiately. */ -xbps_object_iterator_t xbps_array_iter_from_dict(xbps_dictionary_t dict, - const char *key); +xbps_object_iterator_t xbps_array_iter_from_dict(xbps_dictionary_t dict, const char *key); /*@}*/ @@ -1207,14 +1195,16 @@ xbps_object_iterator_t xbps_array_iter_from_dict(xbps_dictionary_t dict, * @retval ENOTSUP No repositories are available. * @retval ENXIO Package depends on invalid dependencies. * @retval EINVAL Any other error ocurred in the process. + * @retval EBUSY The xbps package must be updated. */ -int xbps_transaction_install_pkg(struct xbps_handle *xhp, - const char *pkg, - bool reinstall); +int xbps_transaction_install_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall); /** * Marks a package as "going to be updated" in the transaction dictionary. - * All repositories in the pool will be used, and newest version + * The first repository that contains an updated version wins. + * + * If bestmaching is enabled (see \a XBPS_FLAG_BESTMATCH), + * all repositories in the pool will be used, and newest version * available will be enqueued if it's greater than current installed * version. * @@ -1227,6 +1217,7 @@ int xbps_transaction_install_pkg(struct xbps_handle *xhp, * @retval ENOTSUP No repositories are available. * @retval ENXIO Package depends on invalid dependencies. * @retval EINVAL Any other error ocurred in the process. + * @retval EBUSY The xbps package must be updated. */ int xbps_transaction_update_pkg(struct xbps_handle *xhp, const char *pkgname); @@ -1238,7 +1229,9 @@ int xbps_transaction_update_pkg(struct xbps_handle *xhp, const char *pkgname); * @param[in] xhp Pointer to the xbps_handle struct. * * @return 0 on success, otherwise an errno value. - * @retval EEXIST All installed package are already up-to-date. + * @retval EBUSY The xbps package must be updated. + * @retval EEXIST All installed packages are already up-to-date. + * @retval EINVAL Any other error ocurred in the process. */ int xbps_transaction_update_packages(struct xbps_handle *xhp); @@ -1257,9 +1250,7 @@ int xbps_transaction_update_packages(struct xbps_handle *xhp); * @retval EINVAL * @retval ENXIO A problem ocurred in the process. */ -int xbps_transaction_remove_pkg(struct xbps_handle *xhp, - const char *pkgname, - bool recursive); +int xbps_transaction_remove_pkg(struct xbps_handle *xhp, const char *pkgname, bool recursive); /** * Finds all package orphans currently installed and adds them into @@ -1308,6 +1299,55 @@ int xbps_transaction_prepare(struct xbps_handle *xhp); */ int xbps_transaction_commit(struct xbps_handle *xhp); +/** + * @enum xbps_trans_type_t + * + * uint8_t representing the pkg transaction type in transaction dictionary. + * + * - XBPS_TRANS_UNKNOWN: Unknown type + * - XBPS_TRANS_INSTALL: pkg will be installed + * - XBPS_TRANS_REINSTALL: pkg will be reinstalled + * - XBPS_TRANS_UPDATE: pkg will be updated + * - XBPS_TRANS_CONFIGURE: pkg will be configured + * - XBPS_TRANS_REMOVE: pkg will be removed + * - XBPS_TRANS_HOLD: pkg won't be updated (on hold mode) + * - XBPS_TRANS_DOWNLOAD: pkg will be downloaded + */ +typedef enum xbps_trans_type { + XBPS_TRANS_UNKNOWN = 0, + XBPS_TRANS_INSTALL, + XBPS_TRANS_REINSTALL, + XBPS_TRANS_UPDATE, + XBPS_TRANS_CONFIGURE, + XBPS_TRANS_REMOVE, + XBPS_TRANS_HOLD, + XBPS_TRANS_DOWNLOAD +} xbps_trans_type_t; + +/** + * Returns the transaction type associated with \a pkg_repod. + * + * See \a xbps_trans_type_t for possible values. + * + * @param[in] pkg_repod Package dictionary stored in a repository. + * + * @return The transaction type associated. + */ +xbps_trans_type_t xbps_transaction_pkg_type(xbps_dictionary_t pkg_repod); + +/** + * Sets the transaction type associated with \a pkg_repod. + * + * See \a xbps_trans_type_t for possible values. + * + * @param[in] pkg_repod Package dictionary stored in a repository. + * @param[in] type The transaction type to set. + * + * @return Returns true on success, false otherwise. + */ + +bool xbps_transaction_pkg_type_set(xbps_dictionary_t pkg_repod, xbps_trans_type_t type); + /*@}*/ /** @addtogroup plist_fetch */ @@ -1479,8 +1519,7 @@ xbps_dictionary_t xbps_rpool_get_pkg(struct xbps_handle *xhp, const char *pkg); * @note When returned dictionary is no longer needed, you must release it * with xbps_object_release(3). */ -xbps_dictionary_t xbps_rpool_get_virtualpkg(struct xbps_handle *xhp, - const char *pkg); +xbps_dictionary_t xbps_rpool_get_virtualpkg(struct xbps_handle *xhp, const char *pkg); /** * Returns a proplib array of strings with reverse dependencies of all @@ -1666,8 +1705,7 @@ xbps_dictionary_t xbps_repo_get_pkg(struct xbps_repo *repo, const char *pkg); * * @return The pkg dictionary on success, NULL otherwise. */ -xbps_dictionary_t xbps_repo_get_virtualpkg(struct xbps_repo *repo, - const char *pkg); +xbps_dictionary_t xbps_repo_get_virtualpkg(struct xbps_repo *repo, const char *pkg); /** * Returns a pkg dictionary of the matching \a plist file from a binary package, @@ -1767,9 +1805,7 @@ typedef enum pkg_state { * * @return 0 on success, otherwise an errno value. */ -int xbps_pkg_state_installed(struct xbps_handle *xhp, - const char *pkgname, - pkg_state_t *state); +int xbps_pkg_state_installed(struct xbps_handle *xhp, const char *pkgname, pkg_state_t *state); /** * Gets package state from a package dictionary \a dict, and sets its @@ -2117,9 +2153,7 @@ bool xbps_pkg_has_rundeps(xbps_dictionary_t dict); * * @return True on match, false otherwise. */ -bool xbps_pkg_arch_match(struct xbps_handle *xhp, - const char *orig, - const char *target); +bool xbps_pkg_arch_match(struct xbps_handle *xhp, const char *orig, const char *target); /** * Converts the 64 bits signed number specified in \a bytes to @@ -2132,6 +2166,10 @@ bool xbps_pkg_arch_match(struct xbps_handle *xhp, * @return A negative number is returned on error, 0 otherwise. */ int xbps_humanize_number(char *buf, int64_t bytes); + +/** + * Wrappers for strlcat() and strlcpy(). + */ size_t xbps_strlcat(char *dest, const char *src, size_t siz); size_t xbps_strlcpy(char *dest, const char *src, size_t siz); /** @@ -2249,8 +2287,7 @@ ssize_t xbps_path_prepend(char *dst, size_t len, const char *prefix); * @return The sanitized path in a buffer. * The returned buffer must be free(3)d when it's no longer necessary. */ -char *xbps_symlink_target(struct xbps_handle *xhp, const char *path, - const char *target); +char *xbps_symlink_target(struct xbps_handle *xhp, const char *path, const char *target); /** * Returns true if any of the fnmatch patterns in \a patterns matches diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index d0a701b5..8d3a9aa9 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -116,23 +116,29 @@ 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 *, const char *, bool); -int HIDDEN xbps_repository_find_deps(struct xbps_handle *, xbps_array_t, - xbps_dictionary_t); xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_conf(struct xbps_handle *, xbps_dictionary_t, const char *); xbps_dictionary_t HIDDEN xbps_find_pkg_in_dict(xbps_dictionary_t, const char *); xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_dict(struct xbps_handle *, xbps_dictionary_t, const char *); xbps_dictionary_t HIDDEN xbps_find_pkg_in_array(xbps_array_t, const char *, - const char *); + xbps_trans_type_t); xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_array(struct xbps_handle *, - xbps_array_t, const char *, const char *); -void HIDDEN xbps_transaction_revdeps(struct xbps_handle *, xbps_array_t); -bool HIDDEN xbps_transaction_shlibs(struct xbps_handle *, xbps_array_t, - xbps_array_t); + xbps_array_t, const char *, xbps_trans_type_t); + +/* transaction */ +bool HIDDEN xbps_transaction_check_revdeps(struct xbps_handle *, xbps_array_t); +bool HIDDEN xbps_transaction_check_shlibs(struct xbps_handle *, xbps_array_t); +bool HIDDEN xbps_transaction_check_replaces(struct xbps_handle *, xbps_array_t); +bool HIDDEN xbps_transaction_check_conflicts(struct xbps_handle *, xbps_array_t); +bool HIDDEN xbps_transaction_store(struct xbps_handle *, xbps_array_t, xbps_dictionary_t, bool); int HIDDEN xbps_transaction_init(struct xbps_handle *); -int HIDDEN xbps_transaction_store(struct xbps_handle *, xbps_array_t, - xbps_dictionary_t, const char *, bool); +int HIDDEN xbps_transaction_files(struct xbps_handle *, + xbps_object_iterator_t); +int HIDDEN xbps_transaction_fetch(struct xbps_handle *, + xbps_object_iterator_t); +int HIDDEN xbps_transaction_pkg_deps(struct xbps_handle *, xbps_array_t, xbps_dictionary_t); + char HIDDEN *xbps_get_remote_repo_string(const char *); int HIDDEN xbps_repo_sync(struct xbps_handle *, const char *); int HIDDEN xbps_file_hash_check_dictionary(struct xbps_handle *, @@ -143,10 +149,8 @@ void HIDDEN xbps_set_cb_fetch(struct xbps_handle *, off_t, off_t, off_t, int HIDDEN xbps_set_cb_state(struct xbps_handle *, xbps_state_t, int, const char *, const char *, ...); int HIDDEN xbps_unpack_binary_pkg(struct xbps_handle *, xbps_dictionary_t); -int HIDDEN xbps_transaction_package_replace(struct xbps_handle *, xbps_array_t); int HIDDEN xbps_remove_pkg(struct xbps_handle *, const char *, bool); int HIDDEN xbps_register_pkg(struct xbps_handle *, xbps_dictionary_t); -void HIDDEN xbps_transaction_conflicts(struct xbps_handle *, xbps_array_t); char HIDDEN *xbps_archive_get_file(struct archive *, struct archive_entry *); xbps_dictionary_t HIDDEN xbps_archive_get_dictionary(struct archive *, struct archive_entry *); @@ -156,9 +160,5 @@ xbps_array_t HIDDEN xbps_get_pkg_fulldeptree(struct xbps_handle *, struct xbps_repo HIDDEN *xbps_regget_repo(struct xbps_handle *, const char *); int HIDDEN xbps_conf_init(struct xbps_handle *); -int HIDDEN xbps_transaction_files(struct xbps_handle *, - xbps_object_iterator_t); -int HIDDEN xbps_transaction_fetch(struct xbps_handle *, - xbps_object_iterator_t); #endif /* !_XBPS_API_IMPL_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 2c932211..65342efa 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -33,18 +33,18 @@ EXTOBJS = external/dewey.o external/fexec.o external/mkpath.o # libxbps OBJS = package_configure.o package_config_files.o package_orphans.o -OBJS += package_remove.o package_state.o +OBJS += package_remove.o package_state.o package_msg.o OBJS += package_unpack.o package_register.o package_script.o verifysig.o -OBJS += package_msg.o transaction_shlibs.o -OBJS += transaction_commit.o transaction_package_replace.o -OBJS += transaction_prepare.o transaction_ops.o transaction_store.o -OBJS += transaction_revdeps.o transaction_conflicts.o -OBJS += transaction_files.o transaction_fetch.o +OBJS += transaction_commit.o transaction_prepare.o +OBJS += transaction_ops.o transaction_store.o transaction_check_replaces.o +OBJS += transaction_check_revdeps.o transaction_check_conflicts.o +OBJS += transaction_check_shlibs.o +OBJS += transaction_files.o transaction_fetch.o transaction_pkg_deps.o OBJS += pubkey2fp.o package_fulldeptree.o OBJS += download.o initend.o pkgdb.o OBJS += plist.o plist_find.o plist_match.o archive.o OBJS += plist_remove.o plist_fetch.o util.o util_path.o util_hash.o -OBJS += repo.o repo_pkgdeps.o repo_sync.o +OBJS += repo.o repo_sync.o OBJS += rpool.o cb_util.o proplib_wrapper.o OBJS += package_alternatives.o OBJS += conf.o log.o diff --git a/lib/package_alternatives.c b/lib/package_alternatives.c index 8631af29..a91d5429 100644 --- a/lib/package_alternatives.c +++ b/lib/package_alternatives.c @@ -330,8 +330,7 @@ xbps_alternatives_unregister(struct xbps_handle *xhp, xbps_dictionary_t pkgd) { xbps_array_t allkeys; xbps_dictionary_t alternatives, pkg_alternatives; - const char *pkgver; - char pkgname[XBPS_NAME_SIZE]; + const char *pkgver, *pkgname; bool update = false; int rv = 0; @@ -346,8 +345,7 @@ xbps_alternatives_unregister(struct xbps_handle *xhp, xbps_dictionary_t pkgd) return 0; xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) - return EINVAL; + xbps_dictionary_get_cstring_nocopy(pkgd, "pkgname", &pkgname); xbps_dictionary_get_bool(pkgd, "alternatives-update", &update); @@ -472,7 +470,7 @@ prune_altgroup(struct xbps_handle *xhp, xbps_dictionary_t repod, static void -remove_obsoletes(struct xbps_handle *xhp, char *pkgname, const char *pkgver, +remove_obsoletes(struct xbps_handle *xhp, const char *pkgname, const char *pkgver, xbps_dictionary_t pkgdb_alts, xbps_dictionary_t repod) { xbps_array_t allkeys; @@ -531,8 +529,7 @@ xbps_alternatives_register(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod) { xbps_array_t allkeys; xbps_dictionary_t alternatives, pkg_alternatives; - const char *pkgver; - char pkgname[XBPS_NAME_SIZE]; + const char *pkgver, *pkgname; int rv = 0; assert(xhp); @@ -550,8 +547,7 @@ xbps_alternatives_register(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod) assert(alternatives); xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver); - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) - return EINVAL; + xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname); /* * Compare alternatives from pkgdb and repo and then remove obsolete diff --git a/lib/package_fulldeptree.c b/lib/package_fulldeptree.c index c1d3fc06..32950024 100644 --- a/lib/package_fulldeptree.c +++ b/lib/package_fulldeptree.c @@ -144,8 +144,7 @@ ordered_depends(struct xbps_handle *xhp, xbps_dictionary_t pkgd, bool rpool, xbps_array_t rdeps, provides; xbps_string_t str; struct item *item, *xitem; - const char *pkgver = NULL; - char pkgn[XBPS_NAME_SIZE]; + const char *pkgver = NULL, *pkgname = NULL; assert(xhp); assert(pkgd); @@ -153,17 +152,15 @@ ordered_depends(struct xbps_handle *xhp, xbps_dictionary_t pkgd, bool rpool, rdeps = xbps_dictionary_get(pkgd, "run_depends"); provides = xbps_dictionary_get(pkgd, "provides"); xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); + xbps_dictionary_get_cstring_nocopy(pkgd, "pkgname", &pkgname); - if (!xbps_pkg_name(pkgn, sizeof(pkgn), pkgver)) { - abort(); - } - item = lookupItem(pkgn); + item = lookupItem(pkgname); if (item) { add_deps_recursive(item, depth == 0); return item; } - item = addItem(rdeps, pkgn); + item = addItem(rdeps, pkgname); item->pkgver = pkgver; assert(item); diff --git a/lib/package_orphans.c b/lib/package_orphans.c index 189e2e74..f5352a9a 100644 --- a/lib/package_orphans.c +++ b/lib/package_orphans.c @@ -99,7 +99,7 @@ xbps_find_pkg_orphans(struct xbps_handle *xhp, xbps_array_t orphans_user) xbps_dbg_printf(xhp, " %s skipped (!automatic)\n", pkgver); continue; } - if (xbps_find_pkg_in_array(array, pkgver, NULL)) { + if (xbps_find_pkg_in_array(array, pkgver, 0)) { xbps_dbg_printf(xhp, " %s orphan (queued)\n", pkgver); continue; } @@ -117,7 +117,7 @@ xbps_find_pkg_orphans(struct xbps_handle *xhp, xbps_array_t orphans_user) const char *revdepver; xbps_array_get_cstring_nocopy(revdeps, i, &revdepver); - if (xbps_find_pkg_in_array(array, revdepver, NULL)) + if (xbps_find_pkg_in_array(array, revdepver, 0)) cnt++; } if (cnt == revdepscnt) { @@ -173,7 +173,7 @@ xbps_find_pkg_orphans(struct xbps_handle *xhp, xbps_array_t orphans_user) cnt = 0; xbps_array_get_cstring_nocopy(rdeps, x, &deppkgver); - if (xbps_find_pkg_in_array(array, deppkgver, NULL)) { + if (xbps_find_pkg_in_array(array, deppkgver, 0)) { xbps_dbg_printf(xhp, " rdep %s already queued\n", deppkgver); continue; } @@ -191,7 +191,7 @@ xbps_find_pkg_orphans(struct xbps_handle *xhp, xbps_array_t orphans_user) xbps_array_get_cstring_nocopy(reqby, j, &reqbydep); xbps_dbg_printf(xhp, " %s processing revdep %s\n", pkgver, reqbydep); - if (xbps_find_pkg_in_array(array, reqbydep, NULL)) + if (xbps_find_pkg_in_array(array, reqbydep, 0)) cnt++; } if (cnt == reqbycnt) { diff --git a/lib/package_register.c b/lib/package_register.c index f3a0caea..7fc9b3aa 100644 --- a/lib/package_register.c +++ b/lib/package_register.c @@ -36,12 +36,12 @@ xbps_register_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkgrd) { xbps_array_t replaces; xbps_dictionary_t pkgd; - char outstr[64], pkgname[XBPS_NAME_SIZE]; time_t t; struct tm tm; struct tm *tmp; - const char *pkgver; + const char *pkgver, *pkgname; char sha256[XBPS_SHA256_SIZE]; + char outstr[64]; char *buf; int rv = 0; bool autoinst = false; @@ -54,11 +54,7 @@ xbps_register_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkgrd) } xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - xbps_dbg_printf(xhp, "%s: invalid pkgname %s\n", __func__, pkgver); - rv = EINVAL; - goto out; - } + xbps_dictionary_get_cstring_nocopy(pkgd, "pkgname", &pkgname); if (xhp->flags & XBPS_FLAG_INSTALL_AUTO) autoinst = true; diff --git a/lib/package_unpack.c b/lib/package_unpack.c index 04305ab9..e947a4eb 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -76,6 +76,7 @@ unpack_archive(struct xbps_handle *xhp, xbps_dictionary_t binpkg_propsd, binpkg_filesd, pkg_filesd, obsd; xbps_array_t array, obsoletes; xbps_data_t data; + xbps_trans_type_t ttype; const struct stat *entry_statp; void *instbuf = NULL, *rembuf = NULL; struct stat st; @@ -83,8 +84,8 @@ unpack_archive(struct xbps_handle *xhp, struct archive_entry *entry; size_t instbufsiz = 0, rembufsiz = 0; ssize_t entry_size; - const char *entry_pname, *transact, *binpkg_pkgver; - char pkgname[XBPS_NAME_SIZE], *buf = NULL; + const char *entry_pname, *binpkg_pkgver, *pkgname; + char *buf = NULL; int ar_rv, rv, error, entry_type, flags; bool preserve, update, file_exists, keep_conf_file; bool skip_extract, force, xucd_stats; @@ -96,21 +97,23 @@ unpack_archive(struct xbps_handle *xhp, ar_rv = rv = error = entry_type = flags = 0; xbps_dictionary_get_bool(pkg_repod, "preserve", &preserve); - xbps_dictionary_get_cstring_nocopy(pkg_repod, "transaction", &transact); + ttype = xbps_transaction_pkg_type(pkg_repod); memset(&xucd, 0, sizeof(xucd)); euid = geteuid(); - if (!xbps_pkg_name(pkgname, XBPS_NAME_SIZE, pkgver)) { - abort(); + if (!xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname)) { + return EINVAL; } - if (xhp->flags & XBPS_FLAG_FORCE_UNPACK) + if (xhp->flags & XBPS_FLAG_FORCE_UNPACK) { force = true; + } - if (strcmp(transact, "update") == 0) + if (ttype == XBPS_TRANS_UPDATE) { update = true; + } /* * Remove obsolete files. diff --git a/lib/pkgdb.c b/lib/pkgdb.c index 04a48593..1721a024 100644 --- a/lib/pkgdb.c +++ b/lib/pkgdb.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2012-2015 Juan Romero Pardines. + * Copyright (c) 2012-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,6 +58,7 @@ * dictionary. */ static int pkgdb_fd = -1; +static bool pkgdb_map_names_done = false; int xbps_pkgdb_lock(struct xbps_handle *xhp) @@ -160,19 +161,21 @@ pkgdb_map_vpkgs(struct xbps_handle *xhp) xbps_array_t provides; xbps_dictionary_t pkgd; const char *pkgver = NULL; - char pkgname[XBPS_NAME_SIZE]; + char pkgname[XBPS_NAME_SIZE] = {0}; + unsigned int cnt; pkgd = xbps_dictionary_get_keysym(xhp->pkgdb, obj); provides = xbps_dictionary_get(pkgd, "provides"); - if (provides == NULL) + cnt = xbps_array_count(provides); + if (!cnt) continue; xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { rv = EINVAL; - break; + goto out; } - for (unsigned int i = 0; i < xbps_array_count(provides); i++) { + for (unsigned int i = 0; i < cnt; i++) { const char *vpkg = NULL; xbps_array_get_cstring_nocopy(provides, i, &vpkg); @@ -180,16 +183,55 @@ pkgdb_map_vpkgs(struct xbps_handle *xhp) xbps_dbg_printf(xhp, "%s: set_cstring vpkg " "%s pkgname %s\n", __func__, vpkg, pkgname); rv = EINVAL; - break; - } else { - xbps_dbg_printf(xhp, "[pkgdb] added vpkg %s for %s\n", - vpkg, pkgname); + goto out; } + xbps_dbg_printf(xhp, "[pkgdb] added vpkg %s for %s\n", vpkg, pkgname); } - if (rv) + } +out: + xbps_object_iterator_release(iter); + return rv; +} + +static int +pkgdb_map_names(struct xbps_handle *xhp) +{ + xbps_object_iterator_t iter; + xbps_object_t obj; + int rv = 0; + + if (pkgdb_map_names_done || !xbps_dictionary_count(xhp->pkgdb)) + return 0; + + /* + * This maps all pkgs in pkgdb to have the "pkgname" string property. + * This way we do it once and not multiple times. + */ + iter = xbps_dictionary_iterator(xhp->pkgdb); + assert(iter); + + while ((obj = xbps_object_iterator_next(iter))) { + xbps_dictionary_t pkgd; + const char *pkgver; + char pkgname[XBPS_NAME_SIZE] = {0}; + + pkgd = xbps_dictionary_get_keysym(xhp->pkgdb, obj); + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) { + continue; + } + if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { + rv = EINVAL; break; + } + if (!xbps_dictionary_set_cstring(pkgd, "pkgname", pkgname)) { + rv = EINVAL; + break; + } } xbps_object_iterator_release(iter); + if (!rv) { + pkgdb_map_names_done = true; + } return rv; } @@ -198,9 +240,12 @@ xbps_pkgdb_init(struct xbps_handle *xhp) { int rv; - assert(xhp != NULL); + assert(xhp); - if (xhp->pkgdb_plist == NULL) + if (xhp->pkgdb) + return 0; + + if (!xhp->pkgdb_plist) xhp->pkgdb_plist = xbps_xasprintf("%s/%s", xhp->metadir, XBPS_PKGDB); #if 0 @@ -208,16 +253,18 @@ xbps_pkgdb_init(struct xbps_handle *xhp) return rv; #endif - if (xhp->pkgdb != NULL) - return 0; if ((rv = xbps_pkgdb_update(xhp, false, true)) != 0) { if (rv != ENOENT) xbps_dbg_printf(xhp, "[pkgdb] cannot internalize " - "pkgdb array: %s\n", strerror(rv)); + "pkgdb dictionary: %s\n", strerror(rv)); return rv; } + if ((rv = pkgdb_map_names(xhp)) != 0) { + xbps_dbg_printf(xhp, "[pkgdb] pkgdb_map_names %s\n", strerror(rv)); + return rv; + } if ((rv = pkgdb_map_vpkgs(xhp)) != 0) { xbps_dbg_printf(xhp, "[pkgdb] pkgdb_map_vpkgs %s\n", strerror(rv)); return rv; @@ -431,9 +478,9 @@ xbps_pkgdb_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg) xbps_dictionary_t xbps_pkgdb_get_pkg_files(struct xbps_handle *xhp, const char *pkg) { - xbps_dictionary_t pkgd, pkgfilesd; + xbps_dictionary_t pkgd; const char *pkgver = NULL; - char pkgname[XBPS_NAME_SIZE], *plist; + char pkgname[XBPS_NAME_SIZE], plist[PATH_MAX]; if (pkg == NULL) return NULL; @@ -446,15 +493,6 @@ xbps_pkgdb_get_pkg_files(struct xbps_handle *xhp, const char *pkg) if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) return NULL; - plist = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); - pkgfilesd = xbps_plist_dictionary_from_file(xhp, plist); - free(plist); - - if (pkgfilesd == NULL) { - xbps_dbg_printf(xhp, "[pkgdb] cannot read %s metadata: %s\n", - pkgver, strerror(errno)); - return NULL; - } - - return pkgfilesd; + snprintf(plist, sizeof(plist)-1, "%s/.%s-files.plist", xhp->metadir, pkgname); + return xbps_plist_dictionary_from_file(xhp, plist); } diff --git a/lib/plist.c b/lib/plist.c index 19c2e0c2..5a06dd81 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -221,8 +221,7 @@ array_replace_dict(xbps_array_t array, bool bypattern) { xbps_object_t obj; - const char *curpkgver; - char curpkgname[XBPS_NAME_SIZE]; + const char *pkgver, *pkgname; assert(xbps_object_type(array) == XBPS_TYPE_ARRAY); assert(xbps_object_type(dict) == XBPS_TYPE_DICTIONARY); @@ -230,26 +229,24 @@ array_replace_dict(xbps_array_t array, for (unsigned int i = 0; i < xbps_array_count(array); i++) { obj = xbps_array_get(array, i); - if (obj == NULL) + if (obj == NULL) { continue; + } + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) { + continue; + } if (bypattern) { /* pkgpattern match */ - xbps_dictionary_get_cstring_nocopy(obj, - "pkgver", &curpkgver); - if (xbps_pkgpattern_match(curpkgver, str)) { - if (!xbps_array_set(array, i, dict)) + if (xbps_pkgpattern_match(pkgver, str)) { + if (!xbps_array_set(array, i, dict)) { return EINVAL; - + } return 0; } } else { /* pkgname match */ - xbps_dictionary_get_cstring_nocopy(obj, - "pkgver", &curpkgver); - if (!xbps_pkg_name(curpkgname, XBPS_NAME_SIZE, curpkgver)) { - abort(); - } - if (strcmp(curpkgname, str) == 0) { + xbps_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); + if (strcmp(pkgname, str) == 0) { if (!xbps_array_set(array, i, dict)) { return EINVAL; } diff --git a/lib/plist_find.c b/lib/plist_find.c index 3709b805..edd1645c 100644 --- a/lib/plist_find.c +++ b/lib/plist_find.c @@ -35,20 +35,29 @@ #include "xbps_api_impl.h" static xbps_dictionary_t -get_pkg_in_array(xbps_array_t array, const char *str, const char *trans, bool virtual) +get_pkg_in_array(xbps_array_t array, const char *str, xbps_trans_type_t tt, bool virtual) { - xbps_object_t obj = NULL; + xbps_object_t obj; xbps_object_iterator_t iter; - const char *tract; + xbps_trans_type_t ttype; bool found = false; + assert(array); + assert(str); + iter = xbps_array_iterator(array); - assert(iter); + if (!iter) + return NULL; while ((obj = xbps_object_iterator_next(iter))) { - const char *pkgver; - char dpkgn[XBPS_NAME_SIZE]; + const char *pkgver = NULL, *pkgname = NULL; + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) { + continue; + } + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname)) { + break; + } if (virtual) { /* * Check if package pattern matches @@ -59,31 +68,19 @@ get_pkg_in_array(xbps_array_t array, const char *str, const char *trans, bool vi break; } else if (xbps_pkgpattern_version(str)) { /* match by pattern against pkgver */ - if (!xbps_dictionary_get_cstring_nocopy(obj, - "pkgver", &pkgver)) - continue; if (xbps_pkgpattern_match(pkgver, str)) { found = true; break; } } else if (xbps_pkg_version(str)) { /* match by exact pkgver */ - if (!xbps_dictionary_get_cstring_nocopy(obj, - "pkgver", &pkgver)) - continue; if (strcmp(str, pkgver) == 0) { found = true; break; } } else { /* match by pkgname */ - if (!xbps_dictionary_get_cstring_nocopy(obj, - "pkgver", &pkgver)) - continue; - if (!xbps_pkg_name(dpkgn, sizeof(dpkgn), pkgver)) { - abort(); - } - if (strcmp(dpkgn, str) == 0) { + if (strcmp(pkgname, str) == 0) { found = true; break; } @@ -91,10 +88,9 @@ get_pkg_in_array(xbps_array_t array, const char *str, const char *trans, bool vi } xbps_object_iterator_release(iter); - if (found && trans && - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract)) { - if (strcmp(tract, trans) == 0) - found = true; + ttype = xbps_transaction_pkg_type(obj); + if (found && tt && (ttype != tt)) { + found = false; } if (!found) { errno = ENOENT; @@ -104,19 +100,19 @@ get_pkg_in_array(xbps_array_t array, const char *str, const char *trans, bool vi } xbps_dictionary_t HIDDEN -xbps_find_pkg_in_array(xbps_array_t a, const char *s, const char *trans) +xbps_find_pkg_in_array(xbps_array_t a, const char *s, xbps_trans_type_t tt) { assert(xbps_object_type(a) == XBPS_TYPE_ARRAY); assert(s); - return get_pkg_in_array(a, s, trans, false); + return get_pkg_in_array(a, s, tt, false); } xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_array(struct xbps_handle *x, xbps_array_t a, const char *s, - const char *trans) + xbps_trans_type_t tt) { xbps_dictionary_t pkgd; const char *vpkg; @@ -126,11 +122,11 @@ xbps_find_virtualpkg_in_array(struct xbps_handle *x, assert(s); if ((vpkg = vpkg_user_conf(x, s, false))) { - if ((pkgd = get_pkg_in_array(a, vpkg, trans, true))) + if ((pkgd = get_pkg_in_array(a, vpkg, tt, true))) return pkgd; } - return get_pkg_in_array(a, s, trans, true); + return get_pkg_in_array(a, s, tt, true); } static xbps_dictionary_t @@ -138,7 +134,10 @@ match_pkg_by_pkgver(xbps_dictionary_t repod, const char *p) { xbps_dictionary_t d = NULL; const char *pkgver = NULL; - char pkgname[XBPS_NAME_SIZE]; + char pkgname[XBPS_NAME_SIZE] = {0}; + + assert(repod); + assert(p); /* exact match by pkgver */ if (!xbps_pkg_name(pkgname, sizeof(pkgname), p)) @@ -161,7 +160,10 @@ match_pkg_by_pattern(xbps_dictionary_t repod, const char *p) { xbps_dictionary_t d = NULL; const char *pkgver = NULL; - char pkgname[XBPS_NAME_SIZE]; + char pkgname[XBPS_NAME_SIZE] = {0}; + + assert(repod); + assert(p); /* match by pkgpattern in pkgver */ if (!xbps_pkgpattern_name(pkgname, sizeof(pkgname), p)) { @@ -193,6 +195,9 @@ vpkg_user_conf(struct xbps_handle *xhp, const char *vpkg, bool only_conf) const char *pkg = NULL; bool found = false; + assert(xhp); + assert(vpkg); + if (only_conf) { d = xhp->vpkgd_conf; } else { @@ -209,9 +214,9 @@ vpkg_user_conf(struct xbps_handle *xhp, const char *vpkg, bool only_conf) while ((obj = xbps_object_iterator_next(iter))) { xbps_string_t rpkg; - char buf[XBPS_NAME_SIZE]; - char *vpkgname; - const char *vpkg_conf; + char buf[XBPS_NAME_SIZE] = {0}; + char *vpkgver = NULL; + const char *vpkgname = NULL, *vpkg_conf = NULL; vpkg_conf = xbps_dictionary_keysym_cstring_nocopy(obj); rpkg = xbps_dictionary_get_keysym(xhp->vpkgd, obj); @@ -221,25 +226,21 @@ vpkg_user_conf(struct xbps_handle *xhp, const char *vpkg, bool only_conf) if (!xbps_pkg_name(buf, XBPS_NAME_SIZE, vpkg_conf)) { abort(); } - vpkgname = strdup(buf); + vpkgname = buf; } else { - vpkgname = strdup(vpkg_conf); + vpkgname = vpkg_conf; } assert(vpkgname); if (xbps_pkgpattern_version(vpkg)) { - char *vpkgver; - if (xbps_pkg_version(vpkg_conf)) { if (!xbps_pkgpattern_match(vpkg_conf, vpkg)) { - free(vpkgname); continue; } } else { vpkgver = xbps_xasprintf("%s-999999_1", vpkg_conf); if (!xbps_pkgpattern_match(vpkgver, vpkg)) { free(vpkgver); - free(vpkgname); continue; } free(vpkgver); @@ -249,16 +250,13 @@ vpkg_user_conf(struct xbps_handle *xhp, const char *vpkg, bool only_conf) abort(); } if (strcmp(buf, vpkgname)) { - free(vpkgname); continue; } } else { if (strcmp(vpkg, vpkgname)) { - free(vpkgname); continue; } } - free(vpkgname); found = true; break; } diff --git a/lib/repo.c b/lib/repo.c index fda4f1e8..acf2f295 100644 --- a/lib/repo.c +++ b/lib/repo.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2012-2015 Juan Romero Pardines. + * Copyright (c) 2012-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -391,45 +391,70 @@ xbps_dictionary_t xbps_repo_get_virtualpkg(struct xbps_repo *repo, const char *pkg) { xbps_dictionary_t pkgd; + const char *pkgver; + char pkgname[XBPS_NAME_SIZE] = {0}; - assert(repo); - assert(pkg); - - if (repo->idx == NULL) + if (!repo || !repo->idx || !pkg) { return NULL; - + } pkgd = xbps_find_virtualpkg_in_dict(repo->xhp, repo->idx, pkg); - if (pkgd) { - xbps_dictionary_set_cstring_nocopy(pkgd, "repository", repo->uri); + if (!pkgd) { + return NULL; + } + if (xbps_dictionary_get(pkgd, "repository") && xbps_dictionary_get(pkgd, "pkgname")) { return pkgd; } - return NULL; + if (!xbps_dictionary_set_cstring_nocopy(pkgd, "repository", repo->uri)) { + return NULL; + } + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) { + return NULL; + } + if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { + return NULL; + } + if (!xbps_dictionary_set_cstring(pkgd, "pkgname", pkgname)) { + return NULL; + } + return pkgd; } xbps_dictionary_t xbps_repo_get_pkg(struct xbps_repo *repo, const char *pkg) { - xbps_dictionary_t pkgd; + xbps_dictionary_t pkgd = NULL; + const char *pkgver; + char pkgname[XBPS_NAME_SIZE] = {0}; - assert(repo); - assert(pkg); - - if (repo->idx == NULL) + if (!repo || !repo->idx || !pkg) { return NULL; - + } /* Try matching vpkg from configuration files */ if ((pkgd = xbps_find_virtualpkg_in_conf(repo->xhp, repo->idx, pkg))) { - xbps_dictionary_set_cstring_nocopy(pkgd, "repository", repo->uri); - return pkgd; + goto add; } /* ... otherwise match a real pkg */ - pkgd = xbps_find_pkg_in_dict(repo->idx, pkg); - if (pkgd) { - xbps_dictionary_set_cstring_nocopy(pkgd, "repository", repo->uri); + if ((pkgd = xbps_find_pkg_in_dict(repo->idx, pkg))) { + goto add; + } + return NULL; +add: + if (xbps_dictionary_get(pkgd, "repository") && xbps_dictionary_get(pkgd, "pkgname")) { return pkgd; } - - return NULL; + if (!xbps_dictionary_set_cstring_nocopy(pkgd, "repository", repo->uri)) { + return NULL; + } + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) { + return NULL; + } + if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { + return NULL; + } + if (!xbps_dictionary_set_cstring(pkgd, "pkgname", pkgname)) { + return NULL; + } + return pkgd; } xbps_dictionary_t diff --git a/lib/transaction_conflicts.c b/lib/transaction_check_conflicts.c similarity index 64% rename from lib/transaction_conflicts.c rename to lib/transaction_check_conflicts.c index e73997fe..165feb5d 100644 --- a/lib/transaction_conflicts.c +++ b/lib/transaction_check_conflicts.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2012-2015 Juan Romero Pardines. + * Copyright (c) 2012-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,32 +39,38 @@ pkg_conflicts_trans(struct xbps_handle *xhp, xbps_array_t array, xbps_dictionary_t pkgd, tpkgd; xbps_object_t obj; xbps_object_iterator_t iter; - const char *cfpkg, *repopkgver, *pkgver, *tract; - char pkgname[XBPS_NAME_SIZE]; - char repopkgname[XBPS_NAME_SIZE]; + xbps_trans_type_t ttype; + const char *cfpkg, *repopkgver, *repopkgname; char *buf; - pkg_cflicts = xbps_dictionary_get(pkg_repod, "conflicts"); - if (xbps_array_count(pkg_cflicts) == 0) - return; + assert(xhp); + assert(array); + assert(pkg_repod); - if (xbps_dictionary_get_cstring_nocopy(pkg_repod, "transaction", &tract)) { - /* ignore pkgs to be removed or on hold */ - if (!strcmp(tract, "remove") || !strcmp(tract, "hold")) - return; + pkg_cflicts = xbps_dictionary_get(pkg_repod, "conflicts"); + if (xbps_array_count(pkg_cflicts) == 0) { + return; + } + + ttype = xbps_transaction_pkg_type(pkg_repod); + if (ttype == XBPS_TRANS_HOLD || ttype == XBPS_TRANS_REMOVE) { + return; } trans_cflicts = xbps_dictionary_get(xhp->transd, "conflicts"); - xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &repopkgver); - - if (!xbps_pkg_name(repopkgname, XBPS_NAME_SIZE, repopkgver)) { - abort(); + if (!xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &repopkgver)) { + return; + } + if (!xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &repopkgname)) { + return; } iter = xbps_array_iterator(pkg_cflicts); assert(iter); while ((obj = xbps_object_iterator_next(iter))) { + const char *pkgver = NULL, *pkgname = NULL; + cfpkg = xbps_string_cstring_nocopy(obj); /* @@ -77,25 +83,25 @@ pkg_conflicts_trans(struct xbps_handle *xhp, xbps_array_t array, continue; /* Ignore itself */ - xbps_dictionary_get_cstring_nocopy(pkgd, - "pkgver", &pkgver); - if (!xbps_pkg_name(pkgname, XBPS_NAME_SIZE, pkgver)) { - abort(); + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgname", &pkgname)) { + break; } if (strcmp(pkgname, repopkgname) == 0) { continue; } + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) { + break; + } /* * If there's a pkg for the conflict in transaction, * ignore it. */ - if ((tpkgd = xbps_find_pkg_in_array(array, pkgname, NULL))) { - xbps_dictionary_get_cstring_nocopy(tpkgd, - "transaction", &tract); - if (!strcmp(tract, "install") || - !strcmp(tract, "update") || - !strcmp(tract, "remove") || - !strcmp(tract, "hold")) { + if ((tpkgd = xbps_find_pkg_in_array(array, pkgname, 0))) { + ttype = xbps_transaction_pkg_type(tpkgd); + if (ttype == XBPS_TRANS_INSTALL || + ttype == XBPS_TRANS_UPDATE || + ttype == XBPS_TRANS_REMOVE || + ttype == XBPS_TRANS_HOLD) { continue; } } @@ -114,23 +120,23 @@ pkg_conflicts_trans(struct xbps_handle *xhp, xbps_array_t array, /* * Check if current pkg conflicts with any pkg in transaction. */ - if ((pkgd = xbps_find_pkg_in_array(array, cfpkg, NULL)) || - (pkgd = xbps_find_virtualpkg_in_array(xhp, array, cfpkg, NULL))) { + if ((pkgd = xbps_find_pkg_in_array(array, cfpkg, 0)) || + (pkgd = xbps_find_virtualpkg_in_array(xhp, array, cfpkg, 0))) { /* ignore pkgs to be removed or on hold */ - if (xbps_dictionary_get_cstring_nocopy(pkgd, - "transaction", &tract)) { - if (!strcmp(tract, "remove") || !strcmp(tract, "hold")) - continue; + ttype = xbps_transaction_pkg_type(pkgd); + if (ttype == XBPS_TRANS_REMOVE || ttype == XBPS_TRANS_HOLD) { + continue; } /* ignore itself */ - xbps_dictionary_get_cstring_nocopy(pkgd, - "pkgver", &pkgver); - if (!xbps_pkg_name(pkgname, XBPS_NAME_SIZE, pkgver)) { - abort(); + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgname", &pkgname)) { + break; } if (strcmp(pkgname, repopkgname) == 0) { continue; } + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) { + break; + } xbps_dbg_printf(xhp, "found conflicting pkgs in " "transaction %s <-> %s (matched by %s [trans])\n", pkgver, repopkgver, cfpkg); @@ -155,48 +161,54 @@ pkgdb_conflicts_cb(struct xbps_handle *xhp, xbps_object_t obj, xbps_dictionary_t pkgd; xbps_object_t obj2; xbps_object_iterator_t iter; - const char *cfpkg, *repopkgver, *pkgver, *tract; - char pkgname[XBPS_NAME_SIZE]; - char repopkgname[XBPS_NAME_SIZE]; + xbps_trans_type_t ttype; + const char *cfpkg, *repopkgver, *repopkgname; char *buf; + int rv = 0; pkg_cflicts = xbps_dictionary_get(obj, "conflicts"); if (xbps_array_count(pkg_cflicts) == 0) return 0; - trans_cflicts = xbps_dictionary_get(xhp->transd, "conflicts"); - xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &repopkgver); - if (!xbps_pkg_name(repopkgname, XBPS_NAME_SIZE, repopkgver)) { - abort(); + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &repopkgver)) { + return EINVAL; + } + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgname", &repopkgname)) { + return EINVAL; } /* if a pkg is in the transaction, ignore the one from pkgdb */ - if (xbps_find_pkg_in_array(pkgs, repopkgname, NULL)) { + if (xbps_find_pkg_in_array(pkgs, repopkgname, 0)) { return 0; } + trans_cflicts = xbps_dictionary_get(xhp->transd, "conflicts"); iter = xbps_array_iterator(pkg_cflicts); assert(iter); while ((obj2 = xbps_object_iterator_next(iter))) { + const char *pkgver = NULL, *pkgname = NULL; + cfpkg = xbps_string_cstring_nocopy(obj2); - if ((pkgd = xbps_find_pkg_in_array(pkgs, cfpkg, NULL)) || - (pkgd = xbps_find_virtualpkg_in_array(xhp, pkgs, cfpkg, NULL))) { - xbps_dictionary_get_cstring_nocopy(pkgd, - "pkgver", &pkgver); + if ((pkgd = xbps_find_pkg_in_array(pkgs, cfpkg, 0)) || + (pkgd = xbps_find_virtualpkg_in_array(xhp, pkgs, cfpkg, 0))) { /* ignore pkgs to be removed or on hold */ - if (xbps_dictionary_get_cstring_nocopy(pkgd, - "transaction", &tract)) { - if (!strcmp(tract, "remove") || !strcmp(tract, "hold")) - continue; + ttype = xbps_transaction_pkg_type(pkgd); + if (ttype == XBPS_TRANS_REMOVE || ttype == XBPS_TRANS_HOLD) { + continue; } /* ignore itself */ - if (!xbps_pkg_name(pkgname, XBPS_NAME_SIZE, pkgver)) { - abort(); + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgname", &pkgname)) { + rv = EINVAL; + break; } if (strcmp(pkgname, repopkgname) == 0) { continue; } + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) { + rv = EINVAL; + break; + } xbps_dbg_printf(xhp, "found conflicting pkgs in " "transaction %s <-> %s (matched by %s [pkgdb])\n", pkgver, repopkgver, cfpkg); @@ -211,20 +223,27 @@ pkgdb_conflicts_cb(struct xbps_handle *xhp, xbps_object_t obj, } } xbps_object_iterator_release(iter); - return 0; + return rv; } -void HIDDEN -xbps_transaction_conflicts(struct xbps_handle *xhp, xbps_array_t pkgs) +bool HIDDEN +xbps_transaction_check_conflicts(struct xbps_handle *xhp, xbps_array_t pkgs) { - xbps_dictionary_t pkgd; + xbps_array_t array; unsigned int i; /* find conflicts in transaction */ for (i = 0; i < xbps_array_count(pkgs); i++) { - pkgd = xbps_array_get(pkgs, i); - pkg_conflicts_trans(xhp, pkgs, pkgd); + pkg_conflicts_trans(xhp, pkgs, xbps_array_get(pkgs, i)); } /* find conflicts in pkgdb */ - (void)xbps_pkgdb_foreach_cb_multi(xhp, pkgdb_conflicts_cb, pkgs); + if (xbps_pkgdb_foreach_cb_multi(xhp, pkgdb_conflicts_cb, pkgs) != 0) { + return false; + } + + array = xbps_dictionary_get(xhp->transd, "conflicts"); + if (xbps_array_count(array) == 0) { + xbps_dictionary_remove(xhp->transd, "conflicts"); + } + return true; } diff --git a/lib/transaction_package_replace.c b/lib/transaction_check_replaces.c similarity index 62% rename from lib/transaction_package_replace.c rename to lib/transaction_check_replaces.c index dcacbfa8..9e4f22ef 100644 --- a/lib/transaction_package_replace.c +++ b/lib/transaction_check_replaces.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011-2015 Juan Romero Pardines. + * Copyright (c) 2011-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,34 +33,47 @@ #include "xbps_api_impl.h" -int HIDDEN -xbps_transaction_package_replace(struct xbps_handle *xhp, xbps_array_t pkgs) +/* + * Processes the array of pkg dictionaries in "pkgs" to + * find matching package replacements via "replaces" pkg obj. + * + * This array contains the unordered list of packages in + * the transaction dictionary. + */ +bool HIDDEN +xbps_transaction_check_replaces(struct xbps_handle *xhp, xbps_array_t pkgs) { + assert(xhp); + assert(pkgs); + for (unsigned int i = 0; i < xbps_array_count(pkgs); i++) { xbps_array_t replaces; xbps_object_t obj, obj2; xbps_object_iterator_t iter; - const char *pkgver; - char pkgname[XBPS_NAME_SIZE]; + xbps_dictionary_t instd, reppkgd; + const char *pkgver = NULL; + char pkgname[XBPS_NAME_SIZE] = {0}; obj = xbps_array_get(pkgs, i); replaces = xbps_dictionary_get(obj, "replaces"); if (replaces == NULL || xbps_array_count(replaces) == 0) continue; + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) { + return false; + } + if (!xbps_pkg_name(pkgname, XBPS_NAME_SIZE, pkgver)) { + return false; + } + iter = xbps_array_iterator(replaces); assert(iter); - xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - if (!xbps_pkg_name(pkgname, XBPS_NAME_SIZE, pkgver)) { - abort(); - } - while ((obj2 = xbps_object_iterator_next(iter)) != NULL) { - xbps_dictionary_t instd, reppkgd; - const char *pattern = NULL, *curpkgver = NULL; - char curpkgname[XBPS_NAME_SIZE]; + const char *curpkgver = NULL, *pattern = NULL; + char curpkgname[XBPS_NAME_SIZE] = {0}; bool instd_auto = false, hold = false; + xbps_trans_type_t ttype; pattern = xbps_string_cstring_nocopy(obj2); /* @@ -71,14 +84,17 @@ xbps_transaction_package_replace(struct xbps_handle *xhp, xbps_array_t pkgs) ((instd = xbps_pkgdb_get_virtualpkg(xhp, pattern)) == NULL)) continue; - xbps_dictionary_get_cstring_nocopy(instd, - "pkgver", &curpkgver); + if (!xbps_dictionary_get_cstring_nocopy(instd, "pkgver", &curpkgver)) { + xbps_object_iterator_release(iter); + return false; + } /* ignore pkgs on hold mode */ if (xbps_dictionary_get_bool(instd, "hold", &hold) && hold) continue; if (!xbps_pkg_name(curpkgname, XBPS_NAME_SIZE, curpkgver)) { - abort(); + xbps_object_iterator_release(iter); + return false; } /* * Check that we are not replacing the same package, @@ -91,32 +107,40 @@ xbps_transaction_package_replace(struct xbps_handle *xhp, xbps_array_t pkgs) * Make sure to not add duplicates. */ xbps_dictionary_get_bool(instd, "automatic-install", &instd_auto); - reppkgd = xbps_find_pkg_in_array(pkgs, curpkgname, NULL); + reppkgd = xbps_find_pkg_in_array(pkgs, curpkgname, 0); if (reppkgd) { - const char *rpkgver = NULL, *tract = NULL; - - xbps_dictionary_get_cstring_nocopy(reppkgd, - "pkgver", &rpkgver); - xbps_dictionary_get_cstring_nocopy(reppkgd, - "transaction", &tract); - if (!strcmp(tract, "remove") || !strcmp(tract, "hold")) + ttype = xbps_transaction_pkg_type(reppkgd); + if (ttype == XBPS_TRANS_REMOVE || ttype == XBPS_TRANS_HOLD) continue; + if (!xbps_dictionary_get_cstring_nocopy(reppkgd, + "pkgver", &curpkgver)) { + xbps_object_iterator_release(iter); + return false; + } if (!xbps_match_virtual_pkg_in_dict(reppkgd, pattern) && - !xbps_pkgpattern_match(rpkgver, pattern)) + !xbps_pkgpattern_match(curpkgver, pattern)) continue; /* * Package contains replaces="pkgpattern", but the * package that should be replaced is also in the * transaction and it's going to be updated. */ - xbps_dictionary_set_bool(reppkgd, - "automatic-install", instd_auto); - xbps_dictionary_set_cstring_nocopy(reppkgd, - "transaction", "remove"); - xbps_dictionary_set_bool(reppkgd, - "replaced", true); - xbps_array_replace_dict_by_name(pkgs, - reppkgd, curpkgname); + if (!xbps_dictionary_set_bool(reppkgd, "automatic-install", instd_auto)) { + xbps_object_iterator_release(iter); + return false; + } + if (!xbps_dictionary_set_bool(reppkgd, "replaced", true)) { + xbps_object_iterator_release(iter); + return false; + } + if (!xbps_transaction_pkg_type_set(reppkgd, XBPS_TRANS_REMOVE)) { + xbps_object_iterator_release(iter); + return false; + } + if (xbps_array_replace_dict_by_name(pkgs, reppkgd, curpkgname) != 0) { + xbps_object_iterator_release(iter); + return false; + } xbps_dbg_printf(xhp, "Package `%s' in transaction will be " "replaced by `%s', matched with `%s'\n", @@ -129,26 +153,33 @@ xbps_transaction_package_replace(struct xbps_handle *xhp, xbps_array_t pkgs) * the automatic-install object. */ if (xbps_match_virtual_pkg_in_dict(obj, pattern)) { - xbps_dictionary_set_bool(obj, - "automatic-install", instd_auto); + if (!xbps_dictionary_set_bool(obj, "automatic-install", instd_auto)) { + xbps_object_iterator_release(iter); + return false; + } } - xbps_dbg_printf(xhp, - "Package `%s' will be replaced by `%s', " - "matched with `%s'\n", curpkgver, pkgver, pattern); /* * Add package dictionary into the transaction and mark * it as to be "removed". */ - xbps_dictionary_set_cstring_nocopy(instd, - "transaction", "remove"); - xbps_dictionary_set_bool(instd, "replaced", true); + if (!xbps_transaction_pkg_type_set(instd, XBPS_TRANS_REMOVE)) { + xbps_object_iterator_release(iter); + return false; + } + if (!xbps_dictionary_set_bool(instd, "replaced", true)) { + xbps_object_iterator_release(iter); + return false; + } if (!xbps_array_add_first(pkgs, instd)) { xbps_object_iterator_release(iter); - return EINVAL; + return false; } + xbps_dbg_printf(xhp, + "Package `%s' will be replaced by `%s', " + "matched with `%s'\n", curpkgver, pkgver, pattern); } xbps_object_iterator_release(iter); } - return 0; + return true; } diff --git a/lib/transaction_revdeps.c b/lib/transaction_check_revdeps.c similarity index 74% rename from lib/transaction_revdeps.c rename to lib/transaction_check_revdeps.c index 43a60cc5..211f1df0 100644 --- a/lib/transaction_revdeps.c +++ b/lib/transaction_check_revdeps.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2013-2015 Juan Romero Pardines. + * Copyright (c) 2013-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,21 +45,20 @@ check_virtual_pkgs(xbps_array_t mdeps, xbps_dictionary_t trans_pkgd, xbps_dictionary_t rev_pkgd) { + xbps_array_t rundeps; xbps_array_t provides; + const char *pkgver, *vpkgver, *revpkgver, *pkgpattern; + char pkgname[XBPS_NAME_SIZE], vpkgname[XBPS_NAME_SIZE]; + char *str = NULL; bool matched = false; + pkgver = vpkgver = revpkgver = pkgpattern = NULL; provides = xbps_dictionary_get(trans_pkgd, "provides"); + for (unsigned int i = 0; i < xbps_array_count(provides); i++) { - xbps_array_t rundeps; - const char *pkgver, *revpkgver, *pkgpattern; - char pkgname[XBPS_NAME_SIZE], vpkgname[XBPS_NAME_SIZE]; - char *vpkgver = NULL, *str = NULL; - - pkgver = revpkgver = pkgpattern = NULL; - xbps_dictionary_get_cstring_nocopy(trans_pkgd, "pkgver", &pkgver); xbps_dictionary_get_cstring_nocopy(rev_pkgd, "pkgver", &revpkgver); - xbps_array_get_cstring(provides, i, &vpkgver); + xbps_array_get_cstring_nocopy(provides, i, &vpkgver); if (!xbps_pkg_name(vpkgname, sizeof(vpkgname), vpkgver)) { break; @@ -87,53 +86,56 @@ check_virtual_pkgs(xbps_array_t mdeps, free(str); matched = true; } - free(vpkgver); } return matched; } static void -broken_pkg(xbps_array_t mdeps, const char *dep, const char *pkg, const char *trans) +broken_pkg(xbps_array_t mdeps, const char *dep, const char *pkg) { char *str; - str = xbps_xasprintf("%s (%s) breaks installed pkg `%s'", pkg, trans, dep); + str = xbps_xasprintf("%s in transaction breaks installed pkg `%s'", pkg, dep); xbps_array_add_cstring(mdeps, str); free(str); } -void HIDDEN -xbps_transaction_revdeps(struct xbps_handle *xhp, xbps_array_t pkgs) +bool HIDDEN +xbps_transaction_check_revdeps(struct xbps_handle *xhp, xbps_array_t pkgs) { xbps_array_t mdeps; + bool error = false; mdeps = xbps_dictionary_get(xhp->transd, "missing_deps"); for (unsigned int i = 0; i < xbps_array_count(pkgs); i++) { - xbps_array_t pkgrdeps; + xbps_array_t pkgrdeps, rundeps; + xbps_dictionary_t revpkgd; xbps_object_t obj; - const char *pkgver, *tract; - char pkgname[XBPS_NAME_SIZE]; + xbps_trans_type_t ttype; + const char *pkgver = NULL, *revpkgver = NULL; + char pkgname[XBPS_NAME_SIZE] = {0}; obj = xbps_array_get(pkgs, i); + /* + * If pkg is on hold, pass to the next one. + */ + ttype = xbps_transaction_pkg_type(obj); + if (ttype == XBPS_TRANS_HOLD) { + continue; + } + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) { + error = true; + goto out; + } + if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { + error = true; + goto out; + } /* * if pkg in transaction is not installed, * pass to next one. */ - xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract); - - /* - * If pkg is on hold, pass to the next one. - */ - if (strcmp(tract, "hold") == 0) { - continue; - } - - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); - } - if (xbps_pkg_is_installed(xhp, pkgname) == 0) { continue; } @@ -156,40 +158,43 @@ xbps_transaction_revdeps(struct xbps_handle *xhp, xbps_array_t pkgs) * Time to validate revdeps for current pkg. */ for (unsigned int x = 0; x < xbps_array_count(pkgrdeps); x++) { - xbps_array_t rundeps; - xbps_dictionary_t revpkgd; - const char *curpkgver = NULL, *revpkgver, *curdep = NULL, *curtract; - char curpkgname[XBPS_NAME_SIZE]; - char curdepname[XBPS_NAME_SIZE]; + const char *curpkgver = NULL; + char curdepname[XBPS_NAME_SIZE] = {0}; + char curpkgname[XBPS_NAME_SIZE] = {0}; bool found = false; - xbps_array_get_cstring_nocopy(pkgrdeps, x, &curpkgver); + if (!xbps_array_get_cstring_nocopy(pkgrdeps, x, &curpkgver)) { + error = true; + goto out; + } if (!xbps_pkg_name(pkgname, sizeof(pkgname), curpkgver)) { - abort(); + error = true; + goto out; } - if ((revpkgd = xbps_find_pkg_in_array(pkgs, pkgname, NULL))) { - xbps_dictionary_get_cstring_nocopy(revpkgd, "transaction", &curtract); - if (strcmp(curtract, "remove") == 0) + if ((revpkgd = xbps_find_pkg_in_array(pkgs, pkgname, 0))) { + ttype = xbps_transaction_pkg_type(revpkgd); + if (ttype == XBPS_TRANS_REMOVE) revpkgd = NULL; } if (revpkgd == NULL) revpkgd = xbps_pkgdb_get_pkg(xhp, curpkgver); + xbps_dictionary_get_cstring_nocopy(revpkgd, "pkgver", &revpkgver); /* * If target pkg is being removed, all its revdeps * will be broken unless those revdeps are also in * the transaction. */ - if (strcmp(tract, "remove") == 0) { + if (ttype == XBPS_TRANS_REMOVE) { if (xbps_dictionary_get(obj, "replaced")) { continue; } - if (xbps_find_pkg_in_array(pkgs, pkgname, "remove")) { + if (xbps_find_pkg_in_array(pkgs, pkgname, XBPS_TRANS_REMOVE)) { continue; } - broken_pkg(mdeps, curpkgver, pkgver, tract); + broken_pkg(mdeps, curpkgver, pkgver); continue; } /* @@ -206,14 +211,16 @@ xbps_transaction_revdeps(struct xbps_handle *xhp, xbps_array_t pkgs) * Find out what dependency is it. */ if (!xbps_pkg_name(curpkgname, sizeof(curpkgname), pkgver)) { - abort(); + return false; } for (unsigned int j = 0; j < xbps_array_count(rundeps); j++) { + const char *curdep; + xbps_array_get_cstring_nocopy(rundeps, j, &curdep); if ((!xbps_pkgpattern_name(curdepname, sizeof(curdepname), curdep)) && (!xbps_pkg_name(curdepname, sizeof(curdepname), curdep))) { - abort(); + return false; } if (strcmp(curdepname, curpkgname) == 0) { found = true; @@ -233,11 +240,17 @@ xbps_transaction_revdeps(struct xbps_handle *xhp, xbps_array_t pkgs) * if a new version of this conflicting package * is in the transaction. */ - if (xbps_find_pkg_in_array(pkgs, pkgname, "update")) { + if (xbps_find_pkg_in_array(pkgs, pkgname, XBPS_TRANS_UPDATE)) { continue; } - broken_pkg(mdeps, curpkgver, pkgver, tract); + broken_pkg(mdeps, curpkgver, pkgver); } - } +out: + if (!error) { + mdeps = xbps_dictionary_get(xhp->transd, "missing_deps"); + if (xbps_array_count(mdeps) == 0) + xbps_dictionary_remove(xhp->transd, "missing_deps"); + } + return error ? false : true; } diff --git a/lib/transaction_shlibs.c b/lib/transaction_check_shlibs.c similarity index 85% rename from lib/transaction_shlibs.c rename to lib/transaction_check_shlibs.c index 5d1b24a9..bbe3de1c 100644 --- a/lib/transaction_shlibs.c +++ b/lib/transaction_check_shlibs.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2014-2016 Juan Romero Pardines. + * Copyright (c) 2014-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -66,7 +66,7 @@ collect_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs, bool req) xbps_object_t obj; xbps_object_iterator_t iter; xbps_dictionary_t d, pd; - const char *pkgver; + const char *pkgname, *pkgver; d = xbps_dictionary_create(); assert(d); @@ -82,21 +82,12 @@ collect_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs, bool req) iter = xbps_array_iterator(pkgs); assert(iter); while ((obj = xbps_object_iterator_next(iter))) { - const char *trans = NULL; - char pkgname[XBPS_NAME_SIZE]; - - if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname)) continue; - if (!xbps_pkg_name(pkgname, XBPS_NAME_SIZE, pkgver)) { - abort(); - } - /* ignore shlibs if pkg is on hold mode */ - if (xbps_dictionary_get_cstring_nocopy(obj, "transaction", &trans)) { - if (!strcmp(trans, "hold")) { - continue; - } + if (xbps_transaction_pkg_type(obj) == XBPS_TRANS_HOLD) { + continue; } xbps_dictionary_set(pd, pkgname, obj); @@ -112,12 +103,10 @@ collect_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs, bool req) while ((obj = xbps_object_iterator_next(iter))) { xbps_array_t shobjs; xbps_dictionary_t pkgd; - const char *trans; pkgd = xbps_dictionary_get_keysym(pd, obj); - if (xbps_dictionary_get_cstring_nocopy(pkgd, "transaction", &trans)) { - if (!strcmp(trans, "remove")) - continue; + if (xbps_transaction_pkg_type(pkgd) == XBPS_TRANS_REMOVE) { + continue; } /* * If pkg does not have the required obj, pass to next one. @@ -146,25 +135,25 @@ collect_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs, bool req) } bool HIDDEN -xbps_transaction_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs, xbps_array_t mshlibs) +xbps_transaction_check_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs) { + xbps_array_t array, mshlibs; xbps_object_t obj, obj2; xbps_object_iterator_t iter; xbps_dictionary_t shrequires, shprovides; - bool unmatched = false; + const char *pkgver = NULL, *shlib = NULL; + char *buf; + bool broken = false; shrequires = collect_shlibs(xhp, pkgs, true); shprovides = collect_shlibs(xhp, pkgs, false); + mshlibs = xbps_dictionary_get(xhp->transd, "missing_shlibs"); /* iterate over shlib-requires to find unmatched shlibs */ iter = xbps_dictionary_iterator(shrequires); assert(iter); while ((obj = xbps_object_iterator_next(iter))) { - xbps_array_t array; - const char *pkgver = NULL, *shlib = NULL; - char *buf; - shlib = xbps_dictionary_keysym_cstring_nocopy(obj); xbps_dbg_printf(xhp, "%s: checking for `%s': ", __func__, shlib); if ((obj2 = xbps_dictionary_get(shprovides, shlib))) { @@ -174,7 +163,7 @@ xbps_transaction_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs, xbps_array_t } xbps_dbg_printf_append(xhp, "not found\n"); - unmatched = true; + broken = true; array = xbps_dictionary_get_keysym(shrequires, obj); for (unsigned int i = 0; i < xbps_array_count(array); i++) { xbps_array_get_cstring_nocopy(array, i, &pkgver); @@ -183,11 +172,13 @@ xbps_transaction_shlibs(struct xbps_handle *xhp, xbps_array_t pkgs, xbps_array_t xbps_array_add_cstring(mshlibs, buf); free(buf); } - xbps_object_release(array); } xbps_object_iterator_release(iter); - /* XXX: not possible to free shrequires without copying values */ + if (!broken) { + xbps_dictionary_remove(xhp->transd, "missing_shlibs"); + } xbps_object_release(shprovides); + xbps_object_release(shrequires); - return unmatched; + return true; } diff --git a/lib/transaction_commit.c b/lib/transaction_commit.c index 9f16f7bc..27500aa8 100644 --- a/lib/transaction_commit.c +++ b/lib/transaction_commit.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2015 Juan Romero Pardines. + * Copyright (c) 2009-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,8 @@ xbps_transaction_commit(struct xbps_handle *xhp) { xbps_object_t obj; xbps_object_iterator_t iter; - const char *pkgver, *tract; + xbps_trans_type_t ttype; + const char *pkgver = NULL; int rv = 0; bool update; @@ -140,10 +141,10 @@ xbps_transaction_commit(struct xbps_handle *xhp) goto out; } while ((obj = xbps_object_iterator_next(iter)) != NULL) { - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract); xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - if (strcmp(tract, "remove") == 0) { + ttype = xbps_transaction_pkg_type(obj); + if (ttype == XBPS_TRANS_REMOVE) { /* * Remove package. */ @@ -157,7 +158,7 @@ xbps_transaction_commit(struct xbps_handle *xhp) } continue; - } else if (strcmp(tract, "configure") == 0) { + } else if (ttype == XBPS_TRANS_CONFIGURE) { /* * Reconfigure pending package. */ @@ -169,7 +170,7 @@ xbps_transaction_commit(struct xbps_handle *xhp) } continue; - } else if (strcmp(tract, "update") == 0) { + } else if (ttype == XBPS_TRANS_UPDATE) { /* * Update a package: execute pre-remove action of * existing package before unpacking new version. @@ -185,13 +186,13 @@ xbps_transaction_commit(struct xbps_handle *xhp) strerror(rv)); goto out; } - } else if (strcmp(tract, "hold") == 0) { + } else if (ttype == XBPS_TRANS_HOLD) { /* * Package is on hold mode, ignore it. */ continue; } else { - /* Install a package */ + /* Install or reinstall package */ xbps_set_cb_state(xhp, XBPS_STATE_INSTALL, 0, pkgver, NULL); } @@ -227,7 +228,8 @@ xbps_transaction_commit(struct xbps_handle *xhp) xbps_object_iterator_reset(iter); /* Force a pkgdb write for all unpacked pkgs in transaction */ - (void)xbps_pkgdb_update(xhp, true, true); + if ((rv = xbps_pkgdb_update(xhp, true, true)) != 0) + goto out; /* * Configure all unpacked packages. @@ -236,16 +238,15 @@ xbps_transaction_commit(struct xbps_handle *xhp) while ((obj = xbps_object_iterator_next(iter)) != NULL) { xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract); - if ((strcmp(tract, "remove") == 0) || - (strcmp(tract, "hold") == 0) || - (strcmp(tract, "configure") == 0)) { + ttype = xbps_transaction_pkg_type(obj); + if (ttype == XBPS_TRANS_REMOVE || ttype == XBPS_TRANS_HOLD || + ttype == XBPS_TRANS_CONFIGURE) { xbps_dbg_printf(xhp, "%s: skipping configuration for " - "%s: %s\n", __func__, pkgver, tract); + "%s: %d\n", __func__, pkgver, ttype); continue; } update = false; - if (strcmp(tract, "update") == 0) + if (ttype == XBPS_TRANS_UPDATE) update = true; rv = xbps_configure_pkg(xhp, pkgver, false, update); @@ -269,8 +270,9 @@ xbps_transaction_commit(struct xbps_handle *xhp) out: xbps_object_iterator_release(iter); - /* Force a pkgdb write for all unpacked pkgs in transaction */ - (void)xbps_pkgdb_update(xhp, true, true); - + if (rv == 0) { + /* Force a pkgdb write for all unpacked pkgs in transaction */ + rv = xbps_pkgdb_update(xhp, true, true); + } return rv; } diff --git a/lib/transaction_fetch.c b/lib/transaction_fetch.c index 92f1d37d..c3cc7ed0 100644 --- a/lib/transaction_fetch.c +++ b/lib/transaction_fetch.c @@ -191,19 +191,21 @@ download_binpkg(struct xbps_handle *xhp, xbps_dictionary_t repo_pkgd) int xbps_transaction_fetch(struct xbps_handle *xhp, xbps_object_iterator_t iter) { - xbps_object_t obj; - const char *trans, *repoloc; - int rv = 0; xbps_array_t fetch = NULL, verify = NULL; + xbps_object_t obj; + xbps_trans_type_t ttype; + const char *repoloc; + int rv = 0; unsigned int i, n; - while ((obj = xbps_object_iterator_next(iter)) != NULL) { - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &trans); - if ((strcmp(trans, "remove") == 0) || - (strcmp(trans, "hold") == 0) || - (strcmp(trans, "configure") == 0)) - continue; + xbps_object_iterator_reset(iter); + while ((obj = xbps_object_iterator_next(iter)) != NULL) { + ttype = xbps_transaction_pkg_type(obj); + if (ttype == XBPS_TRANS_REMOVE || ttype == XBPS_TRANS_HOLD || + ttype == XBPS_TRANS_CONFIGURE) { + continue; + } xbps_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); /* diff --git a/lib/transaction_files.c b/lib/transaction_files.c index 2fe39d95..8c12cd7e 100644 --- a/lib/transaction_files.c +++ b/lib/transaction_files.c @@ -665,17 +665,15 @@ collect_binpkg_files(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod, struct archive *ar = NULL; struct archive_entry *entry; struct stat st; - const char *pkgver; - char *bpkg, pkgname[XBPS_NAME_SIZE]; + const char *pkgver, *pkgname; + char *bpkg; /* size_t entry_size; */ int rv = 0, pkg_fd = -1; xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver); assert(pkgver); - - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); - } + xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname); + assert(pkgname); bpkg = xbps_repository_pkg_path(xhp, pkg_repod); if (bpkg == NULL) { @@ -769,14 +767,13 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter) { xbps_dictionary_t pkgd, filesd; xbps_object_t obj; - const char *trans, *pkgver; - char pkgname[XBPS_NAME_SIZE]; + xbps_trans_type_t ttype; + const char *pkgver, *pkgname; int rv = 0; unsigned int idx = 0; - iter = xbps_array_iter_from_dict(xhp->transd, "packages"); - if (iter == NULL) - return EINVAL; + assert(xhp); + assert(iter); while ((obj = xbps_object_iterator_next(iter)) != NULL) { bool update = false; @@ -787,22 +784,22 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter) */ idx++; - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &trans); - assert(trans); - - if ((strcmp(trans, "hold") == 0) || - (strcmp(trans, "configure") == 0)) + /* ignore pkgs in hold mode or in unpacked state */ + ttype = xbps_transaction_pkg_type(obj); + if (ttype == XBPS_TRANS_HOLD || ttype == XBPS_TRANS_CONFIGURE) { continue; - - xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - - assert(pkgver); - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); } - update = strcmp(trans, "update") == 0; - if (update || (strcmp(trans, "install") == 0)) { + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) { + return EINVAL; + } + if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname)) { + return EINVAL; + } + + update = (ttype == XBPS_TRANS_UPDATE); + + if (ttype == XBPS_TRANS_INSTALL || ttype == XBPS_TRANS_UPDATE) { xbps_set_cb_state(xhp, XBPS_STATE_FILES, 0, pkgver, "%s: collecting files...", pkgver); rv = collect_binpkg_files(xhp, obj, idx, update); @@ -822,7 +819,7 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter) if (pkgd) { const char *oldpkgver; bool preserve = false; - bool removepkg = strcmp(trans, "remove") == 0; + bool removepkg = (ttype == XBPS_TRANS_REMOVE); xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &oldpkgver); if (!xbps_dictionary_get_bool(obj, "preserve", &preserve)) @@ -858,9 +855,8 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter) } out: - xbps_object_iterator_release(iter); - if (rv != 0) return rv; + return collect_obsoletes(xhp); } diff --git a/lib/transaction_ops.c b/lib/transaction_ops.c index a7b93b74..e0964bd8 100644 --- a/lib/transaction_ops.c +++ b/lib/transaction_ops.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2019 Juan Romero Pardines. + * Copyright (c) 2009-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,22 +52,16 @@ * Text inside of white boxes are the key associated with the object, its * data type is specified on its edge, i.e string, array, integer, dictionary. */ -enum { - TRANS_INSTALL = 1, - TRANS_UPDATE, - TRANS_REINSTALL -}; - static int -trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall, - bool hold) +trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall) { xbps_dictionary_t pkg_pkgdb = NULL, pkg_repod = NULL; xbps_array_t pkgs; - const char *repoloc, *repopkgver, *instpkgver, *reason; - char pkgname[XBPS_NAME_SIZE]; - int action = 0, rv = 0; pkg_state_t state = 0; + xbps_trans_type_t ttype; + const char *repoloc, *repopkgver, *instpkgver, *pkgname; + char buf[XBPS_NAME_SIZE] = {0}; + int rv = 0; bool autoinst = false, repolock = false; assert(pkg != NULL); @@ -75,14 +69,15 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall, /* * Find out if pkg is installed first. */ - if (xbps_pkg_name(pkgname, sizeof(pkgname), pkg)) { - pkg_pkgdb = xbps_pkgdb_get_pkg(xhp, pkgname); + if (xbps_pkg_name(buf, sizeof(buf), pkg)) { + pkg_pkgdb = xbps_pkgdb_get_pkg(xhp, buf); } else { pkg_pkgdb = xbps_pkgdb_get_pkg(xhp, pkg); } if (xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { pkg_pkgdb = NULL; + ttype = XBPS_TRANS_DOWNLOAD; } /* @@ -90,21 +85,17 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall, */ if (pkg_pkgdb == NULL) { /* pkg not installed, perform installation */ - action = TRANS_INSTALL; - reason = "install"; + ttype = XBPS_TRANS_INSTALL; if (((pkg_repod = xbps_rpool_get_pkg(xhp, pkg)) == NULL) && ((pkg_repod = xbps_rpool_get_virtualpkg(xhp, pkg)) == NULL)) { /* not found */ return ENOENT; } } else { - /* pkg installed, update or reinstall */ - if (!reinstall) { - action = TRANS_UPDATE; - reason = "update"; + if (reinstall) { + ttype = XBPS_TRANS_REINSTALL; } else { - action = TRANS_REINSTALL; - reason = "install"; + ttype = XBPS_TRANS_UPDATE; } xbps_dictionary_get_bool(pkg_pkgdb, "repolock", &repolock); if (repolock) { @@ -129,7 +120,7 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall, xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &repopkgver); - if (action == TRANS_UPDATE) { + if (ttype == XBPS_TRANS_UPDATE) { /* * Compare installed version vs best pkg available in repos * for pkg updates. @@ -145,7 +136,7 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall, repopkgver, instpkgver, repoloc); return EEXIST; } - } else if (action == TRANS_REINSTALL) { + } else if (ttype == XBPS_TRANS_REINSTALL) { /* * For reinstallation check if installed version is less than * or equal to the pkg in repos, if true, continue with reinstallation; @@ -153,8 +144,7 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall, */ xbps_dictionary_get_cstring_nocopy(pkg_pkgdb, "pkgver", &instpkgver); if (xbps_cmpver(repopkgver, instpkgver) == 1) { - action = TRANS_UPDATE; - reason = "update"; + ttype = XBPS_TRANS_UPDATE; } } @@ -178,16 +168,16 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall, * Find out if package being updated matches the one already * in transaction, in that case ignore it. */ - if (action == TRANS_UPDATE) { - if (xbps_find_pkg_in_array(pkgs, repopkgver, NULL)) { + if (ttype == XBPS_TRANS_UPDATE) { + if (xbps_find_pkg_in_array(pkgs, repopkgver, 0)) { xbps_dbg_printf(xhp, "[update] `%s' already queued in " "transaction.\n", repopkgver); return EEXIST; } } - if (!xbps_pkg_name(pkgname, sizeof(pkgname), repopkgver)) { - abort(); + if (!xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname)) { + return EINVAL; } /* * Set package state in dictionary with same state than the @@ -204,22 +194,24 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall, return rv; } - if ((action == TRANS_INSTALL) && (state == XBPS_PKG_STATE_UNPACKED)) - reason = "configure"; - else if (state == XBPS_PKG_STATE_NOT_INSTALLED) - reason = "install"; - else if ((action == TRANS_UPDATE) && hold) - reason = "hold"; - + if (ttype != XBPS_TRANS_HOLD) { + if (state == XBPS_PKG_STATE_UNPACKED) + ttype = XBPS_TRANS_CONFIGURE; + else if (state == XBPS_PKG_STATE_NOT_INSTALLED) + ttype = XBPS_TRANS_INSTALL; + } /* - * Set transaction obj reason. + * Store pkgd from repo into the transaction. */ - if (!xbps_dictionary_set_cstring_nocopy(pkg_repod, - "transaction", reason)) { + if (!xbps_transaction_pkg_type_set(pkg_repod, ttype)) { return EINVAL; } - return xbps_transaction_store(xhp, pkgs, pkg_repod, reason, false); + if (!xbps_transaction_store(xhp, pkgs, pkg_repod, false)) { + return EINVAL; + } + + return 0; } /* @@ -230,8 +222,7 @@ xbps_autoupdate(struct xbps_handle *xhp) { xbps_array_t rdeps; xbps_dictionary_t pkgd; - const char *pkgver; - char pkgname[XBPS_NAME_SIZE]; + const char *pkgver = NULL, *pkgname = NULL; int rv; /* @@ -242,12 +233,14 @@ xbps_autoupdate(struct xbps_handle *xhp) ((pkgd = xbps_pkgdb_get_virtualpkg(xhp, "xbps")) == NULL)) return 0; - xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); - - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) { + return EINVAL; } - rv = trans_find_pkg(xhp, pkgname, false, false); + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgname", &pkgname)) { + return EINVAL; + } + + rv = trans_find_pkg(xhp, pkgname, false); xbps_dbg_printf(xhp, "%s: trans_find_pkg xbps: %d\n", __func__, rv); @@ -259,7 +252,7 @@ xbps_autoupdate(struct xbps_handle *xhp) rdeps = xbps_pkgdb_get_pkg_revdeps(xhp, "xbps"); for (unsigned int i = 0; i < xbps_array_count(rdeps); i++) { const char *curpkgver = NULL; - char curpkgn[XBPS_NAME_SIZE]; + char curpkgn[XBPS_NAME_SIZE] = {0}; xbps_array_get_cstring_nocopy(rdeps, i, &curpkgver); xbps_dbg_printf(xhp, "%s: processing revdep %s\n", __func__, curpkgver); @@ -267,7 +260,7 @@ xbps_autoupdate(struct xbps_handle *xhp) if (!xbps_pkg_name(curpkgn, sizeof(curpkgn), curpkgver)) { abort(); } - rv = trans_find_pkg(xhp, curpkgn, false, false); + rv = trans_find_pkg(xhp, curpkgn, false); xbps_dbg_printf(xhp, "%s: trans_find_pkg revdep %s: %d\n", __func__, curpkgver, rv); if (rv && rv != ENOENT && rv != EEXIST && rv != ENODEV) return -1; @@ -300,6 +293,7 @@ xbps_transaction_update_packages(struct xbps_handle *xhp) { xbps_object_t obj; xbps_object_iterator_t iter; + xbps_dictionary_t pkgd; bool newpkg_found = false; int rv = 0; @@ -319,23 +313,21 @@ xbps_transaction_update_packages(struct xbps_handle *xhp) assert(iter); while ((obj = xbps_object_iterator_next(iter))) { - xbps_dictionary_t pkgd; - const char *pkgver; - char pkgname[XBPS_NAME_SIZE]; - bool hold = false; + const char *pkgver = NULL; + char pkgname[XBPS_NAME_SIZE] = {0}; pkgd = xbps_dictionary_get_keysym(xhp->pkgdb, obj); - if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) + if (xbps_dictionary_get(pkgd, "hold")) { + continue; + } + if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) { continue; - xbps_dictionary_get_bool(pkgd, "hold", &hold); - if (hold) { - xbps_dbg_printf(xhp, "[rpool] package `%s' " - "on hold, ignoring updates.\n", pkgver); } if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); + rv = EINVAL; + break; } - rv = trans_find_pkg(xhp, pkgname, false, hold); + rv = trans_find_pkg(xhp, pkgname, false); xbps_dbg_printf(xhp, "%s: trans_find_pkg %s: %d\n", __func__, pkgver, rv); if (rv == 0) { newpkg_found = true; @@ -374,24 +366,31 @@ xbps_transaction_update_pkg(struct xbps_handle *xhp, const char *pkg) break; } + /* update its reverse dependencies */ rdeps = xbps_pkgdb_get_pkg_revdeps(xhp, pkg); if (xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { rdeps = NULL; } for (unsigned int i = 0; i < xbps_array_count(rdeps); i++) { const char *pkgver = NULL; - char pkgname[XBPS_NAME_SIZE]; + char pkgname[XBPS_NAME_SIZE] = {0}; - xbps_array_get_cstring_nocopy(rdeps, i, &pkgver); - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); + if (!xbps_array_get_cstring_nocopy(rdeps, i, &pkgver)) { + rv = EINVAL; + break; } - rv = trans_find_pkg(xhp, pkgname, false, false); + if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { + rv = EINVAL; + break; + } + rv = trans_find_pkg(xhp, pkgname, false); xbps_dbg_printf(xhp, "%s: trans_find_pkg %s: %d\n", __func__, pkgver, rv); - if (rv && rv != ENOENT && rv != EEXIST && rv != ENODEV) + if (rv && rv != ENOENT && rv != EEXIST && rv != ENODEV) { return rv; + } } - rv = trans_find_pkg(xhp, pkg, false, false); + /* add pkg repod */ + rv = trans_find_pkg(xhp, pkg, false); xbps_dbg_printf(xhp, "%s: trans_find_pkg %s: %d\n", __func__, pkg, rv); return rv; } @@ -418,24 +417,30 @@ xbps_transaction_install_pkg(struct xbps_handle *xhp, const char *pkg, break; } + /* update its reverse dependencies */ rdeps = xbps_pkgdb_get_pkg_revdeps(xhp, pkg); if (xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { rdeps = NULL; } for (unsigned int i = 0; i < xbps_array_count(rdeps); i++) { const char *pkgver = NULL; - char pkgname[XBPS_NAME_SIZE]; + char pkgname[XBPS_NAME_SIZE] = {0}; - xbps_array_get_cstring_nocopy(rdeps, i, &pkgver); - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); + if (!xbps_array_get_cstring_nocopy(rdeps, i, &pkgver)) { + rv = EINVAL; + break; } - rv = trans_find_pkg(xhp, pkgname, false, false); + if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { + rv = EINVAL; + break; + } + rv = trans_find_pkg(xhp, pkgname, false); xbps_dbg_printf(xhp, "%s: trans_find_pkg %s: %d\n", __func__, pkgver, rv); - if (rv && rv != ENOENT && rv != EEXIST && rv != ENODEV) + if (rv && rv != ENOENT && rv != EEXIST && rv != ENODEV) { return rv; + } } - rv = trans_find_pkg(xhp, pkg, reinstall, false); + rv = trans_find_pkg(xhp, pkg, reinstall); xbps_dbg_printf(xhp, "%s: trans_find_pkg %s: %d\n", __func__, pkg, rv); return rv; } @@ -448,10 +453,10 @@ xbps_transaction_remove_pkg(struct xbps_handle *xhp, xbps_dictionary_t pkgd; xbps_array_t pkgs, orphans, orphans_pkg; xbps_object_t obj; - const char *pkgver; int rv = 0; - assert(pkgname != NULL); + assert(xhp); + assert(pkgname); if ((pkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) { /* pkg not installed */ @@ -482,11 +487,10 @@ xbps_transaction_remove_pkg(struct xbps_handle *xhp, for (unsigned int i = 0; i < xbps_array_count(orphans); i++) { obj = xbps_array_get(orphans, i); - xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - xbps_dictionary_set_cstring_nocopy(obj, "transaction", "remove"); - if ((rv = xbps_transaction_store(xhp, pkgs, obj, "remove", false)) != 0) + xbps_transaction_pkg_type_set(obj, XBPS_TRANS_REMOVE); + if (!xbps_transaction_store(xhp, pkgs, obj, false)) { return EINVAL; - xbps_dbg_printf(xhp, "%s: added into transaction (remove).\n", pkgver); + } } xbps_object_release(orphans); return rv; @@ -495,11 +499,10 @@ rmpkg: /* * Add pkg dictionary into the transaction pkgs queue. */ - xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); - xbps_dictionary_set_cstring_nocopy(pkgd, "transaction", "remove"); - if ((rv = xbps_transaction_store(xhp, pkgs, pkgd, "remove", false)) != 0) + xbps_transaction_pkg_type_set(pkgd, XBPS_TRANS_REMOVE); + if (!xbps_transaction_store(xhp, pkgs, pkgd, false)) { return EINVAL; - xbps_dbg_printf(xhp, "%s: added into transaction (remove).\n", pkgver); + } return rv; } @@ -508,13 +511,11 @@ xbps_transaction_autoremove_pkgs(struct xbps_handle *xhp) { xbps_array_t orphans, pkgs; xbps_object_t obj; - const char *pkgver; int rv = 0; orphans = xbps_find_pkg_orphans(xhp, NULL); if (xbps_array_count(orphans) == 0) { /* no orphans? we are done */ - rv = ENOENT; goto out; } /* @@ -529,15 +530,56 @@ xbps_transaction_autoremove_pkgs(struct xbps_handle *xhp) */ for (unsigned int i = 0; i < xbps_array_count(orphans); i++) { obj = xbps_array_get(orphans, i); - xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - xbps_dictionary_set_cstring_nocopy(obj, - "transaction", "remove"); - xbps_array_add(pkgs, obj); - xbps_dbg_printf(xhp, "%s: added (remove).\n", pkgver); + xbps_transaction_pkg_type_set(obj, XBPS_TRANS_REMOVE); + if (!xbps_transaction_store(xhp, pkgs, obj, false)) { + rv = EINVAL; + goto out; + } } out: - if (orphans != NULL) + if (orphans) xbps_object_release(orphans); return rv; } + +xbps_trans_type_t +xbps_transaction_pkg_type(xbps_dictionary_t pkg_repod) +{ + uint8_t r; + + if (xbps_object_type(pkg_repod) != XBPS_TYPE_DICTIONARY) + return 0; + + if (!xbps_dictionary_get_uint8(pkg_repod, "transaction", &r)) + return 0; + + return r; +} + +bool +xbps_transaction_pkg_type_set(xbps_dictionary_t pkg_repod, xbps_trans_type_t ttype) +{ + uint8_t r; + + if (xbps_object_type(pkg_repod) != XBPS_TYPE_DICTIONARY) + return false; + + switch (ttype) { + case XBPS_TRANS_INSTALL: + case XBPS_TRANS_UPDATE: + case XBPS_TRANS_CONFIGURE: + case XBPS_TRANS_REMOVE: + case XBPS_TRANS_REINSTALL: + case XBPS_TRANS_HOLD: + case XBPS_TRANS_DOWNLOAD: + break; + default: + return false; + } + r = ttype; + if (!xbps_dictionary_set_uint8(pkg_repod, "transaction", r)) + return false; + + return true; +} diff --git a/lib/repo_pkgdeps.c b/lib/transaction_pkg_deps.c similarity index 79% rename from lib/repo_pkgdeps.c rename to lib/transaction_pkg_deps.c index 2bea3d14..7c2ace2e 100644 --- a/lib/repo_pkgdeps.c +++ b/lib/transaction_pkg_deps.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2016 Juan Romero Pardines. + * Copyright (c) 2008-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -109,35 +109,45 @@ out: #define MAX_DEPTH 512 static int -find_repo_deps(struct xbps_handle *xhp, - xbps_array_t unsorted, /* array of unsorted deps */ - xbps_array_t pkg_rdeps_array, /* current pkg rundeps array */ - xbps_array_t pkg_provides, /* current pkg provides array */ - const char *curpkg, /* current pkgver */ - unsigned short *depth) /* max recursion depth */ +repo_deps(struct xbps_handle *xhp, + xbps_array_t pkgs, /* array of pkgs */ + xbps_dictionary_t pkg_repod, /* pkg repo dictionary */ + unsigned short *depth) /* max recursion depth */ { + xbps_array_t pkg_rdeps = NULL, pkg_provides = NULL; + xbps_dictionary_t curpkgd = NULL; + xbps_trans_type_t ttype; + pkg_state_t state; xbps_object_t obj; xbps_object_iterator_t iter; + const char *curpkg = NULL, *reqpkg = NULL, *pkgver_q = NULL; + char pkgname[XBPS_NAME_SIZE], reqpkgname[XBPS_NAME_SIZE]; int rv = 0; + assert(xhp); + assert(pkgs); + assert(pkg_repod); + if (*depth >= MAX_DEPTH) return ELOOP; + xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &curpkg); + pkg_provides = xbps_dictionary_get(pkg_repod, "provides"); /* * Iterate over the list of required run dependencies for * current package. */ - iter = xbps_array_iterator(pkg_rdeps_array); + pkg_rdeps = xbps_dictionary_get(pkg_repod, "run_depends"); + if (xbps_array_count(pkg_rdeps) == 0) + goto out; + + iter = xbps_array_iterator(pkg_rdeps); assert(iter); while ((obj = xbps_object_iterator_next(iter))) { - xbps_array_t curpkgrdeps = NULL, curpkgprovides = NULL; - xbps_dictionary_t curpkgd = NULL; - pkg_state_t state; - const char *reqpkg, *pkgver_q, *reason = NULL; - char pkgname[XBPS_NAME_SIZE], reqpkgname[XBPS_NAME_SIZE]; bool error = false, foundvpkg = false; + ttype = XBPS_TRANS_UNKNOWN; reqpkg = xbps_string_cstring_nocopy(obj); if (xhp->flags & XBPS_FLAG_DEBUG) { @@ -174,8 +184,8 @@ find_repo_deps(struct xbps_handle *xhp, * Pass 2: check if required dependency has been already * added in the transaction dictionary. */ - if ((curpkgd = xbps_find_pkg_in_array(unsorted, reqpkg, NULL)) || - (curpkgd = xbps_find_virtualpkg_in_array(xhp, unsorted, reqpkg, NULL))) { + if ((curpkgd = xbps_find_pkg_in_array(pkgs, reqpkg, 0)) || + (curpkgd = xbps_find_virtualpkg_in_array(xhp, pkgs, reqpkg, 0))) { xbps_dictionary_get_cstring_nocopy(curpkgd, "pkgver", &pkgver_q); xbps_dbg_printf_append(xhp, " (%s queued)\n", pkgver_q); continue; @@ -199,7 +209,6 @@ find_repo_deps(struct xbps_handle *xhp, curpkgd = NULL; } - if (curpkgd == NULL) { if (errno && errno != ENOENT) { /* error */ @@ -209,7 +218,7 @@ find_repo_deps(struct xbps_handle *xhp, } /* Required dependency not installed */ xbps_dbg_printf_append(xhp, "not installed.\n"); - reason = "install"; + ttype = XBPS_TRANS_INSTALL; state = XBPS_PKG_STATE_NOT_INSTALLED; } else { /* @@ -244,18 +253,20 @@ find_repo_deps(struct xbps_handle *xhp, if (strcmp(pkgname, curpkgname)) { xbps_dbg_printf_append(xhp, "not installed `%s (vpkg)'", pkgver_q); if (xbps_dictionary_get(curpkgd, "hold")) { + ttype = XBPS_TRANS_HOLD; xbps_dbg_printf_append(xhp, " on hold state! ignoring package.\n"); } else { xbps_dbg_printf_append(xhp, "\n"); - reason = "install"; + ttype = XBPS_TRANS_INSTALL; } } else { xbps_dbg_printf_append(xhp, "installed `%s', must be updated", pkgver_q); if (xbps_dictionary_get(curpkgd, "hold")) { xbps_dbg_printf_append(xhp, " on hold state! ignoring package.\n"); + ttype = XBPS_TRANS_HOLD; } else { xbps_dbg_printf_append(xhp, "\n"); - reason = "update"; + ttype = XBPS_TRANS_UPDATE; } } } else if (rv == 1) { @@ -269,7 +280,7 @@ find_repo_deps(struct xbps_handle *xhp, * configure pkg. */ xbps_dbg_printf_append(xhp, "installed `%s', must be configured.\n", pkgver_q); - reason = "configure"; + ttype = XBPS_TRANS_CONFIGURE; } else if (state == XBPS_PKG_STATE_INSTALLED) { /* * Package matches the dependency pattern and is fully installed, @@ -285,6 +296,10 @@ find_repo_deps(struct xbps_handle *xhp, } } if (xbps_dictionary_get(curpkgd, "hold")) { + if (!xbps_transaction_pkg_type_set(curpkgd, XBPS_TRANS_HOLD)) { + rv = EINVAL; + break; + } xbps_dbg_printf(xhp, "%s on hold state! ignoring package.\n", curpkg); continue; } @@ -330,14 +345,14 @@ find_repo_deps(struct xbps_handle *xhp, } if (strcmp(pkgname, reqpkgname) == 0) { xbps_dbg_printf_append(xhp, "[ignoring wrong dependency %s (depends on itself)]\n", reqpkg); - xbps_remove_string_from_array(pkg_rdeps_array, reqpkg); + xbps_remove_string_from_array(pkg_rdeps, reqpkg); continue; } /* * Installed package must be updated, check if dependency is * satisfied. */ - if (!strcmp(reason, "update")) { + if (ttype == XBPS_TRANS_UPDATE) { switch (xbps_pkgpattern_match(pkgver_q, reqpkg)) { case 0: /* nomatch */ break; @@ -351,7 +366,7 @@ find_repo_deps(struct xbps_handle *xhp, * So dependency pattern matching didn't * succeed... return ENODEV. */ - if (xbps_find_pkg_in_array(unsorted, pkgname, "update")) { + if (xbps_find_pkg_in_array(pkgs, pkgname, XBPS_TRANS_UPDATE)) { error = true; rv = ENODEV; } @@ -364,76 +379,68 @@ find_repo_deps(struct xbps_handle *xhp, if (error) break; } - - /* - * If package doesn't have rundeps, pass to the next one. - */ - curpkgrdeps = xbps_dictionary_get(curpkgd, "run_depends"); - if (curpkgrdeps == NULL) { + pkg_rdeps = xbps_dictionary_get(curpkgd, "run_depends"); + if (xbps_array_count(pkg_rdeps)) { /* - * Package is on repo, add it into the transaction dictionary. + * Process rundeps for current pkg found in rpool. */ - xbps_dictionary_set_cstring_nocopy(curpkgd, "transaction", reason); - rv = xbps_transaction_store(xhp, unsorted, curpkgd, reason, true); + if (xhp->flags & XBPS_FLAG_DEBUG) { + xbps_dbg_printf(xhp, "%s", ""); + for (unsigned short x = 0; x < *depth; x++) { + xbps_dbg_printf_append(xhp, " "); + } + xbps_dbg_printf_append(xhp, "%s: finding dependencies:\n", pkgver_q); + } + (*depth)++; + rv = repo_deps(xhp, pkgs, curpkgd, depth); if (rv != 0) { - xbps_dbg_printf(xhp, "xbps_transaction_store failed for `%s': %s\n", reqpkg, strerror(rv)); + xbps_dbg_printf(xhp, "Error checking %s for rundeps: %s\n", reqpkg, strerror(rv)); break; } - continue; } - - if (xhp->flags & XBPS_FLAG_DEBUG) { - xbps_dbg_printf(xhp, "%s", ""); - for (unsigned short x = 0; x < *depth; x++) { - xbps_dbg_printf_append(xhp, " "); - } - xbps_dbg_printf_append(xhp, "%s: finding dependencies:\n", pkgver_q); + if (xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { + ttype = XBPS_TRANS_DOWNLOAD; + } else if (xbps_dictionary_get(curpkgd, "hold")) { + ttype = XBPS_TRANS_HOLD; } /* - * Recursively find rundeps for current pkg dictionary. + * All deps were processed, store pkg in transaction. */ - (*depth)++; - curpkgprovides = xbps_dictionary_get(curpkgd, "provides"); - rv = find_repo_deps(xhp, unsorted, curpkgrdeps, curpkgprovides, pkgver_q, depth); - if (rv != 0) { - xbps_dbg_printf(xhp, "Error checking %s for rundeps: %s\n", reqpkg, strerror(rv)); + if (!xbps_transaction_pkg_type_set(curpkgd, ttype)) { + rv = EINVAL; + xbps_dbg_printf(xhp, "xbps_transaction_store failed for `%s': %s\n", reqpkg, strerror(rv)); break; } - /* - * Package is on repo, add it into the transaction dictionary. - */ - xbps_dictionary_set_cstring_nocopy(curpkgd, "transaction", reason); - rv = xbps_transaction_store(xhp, unsorted, curpkgd, reason, true); - if (rv != 0) { + if (!xbps_transaction_store(xhp, pkgs, curpkgd, true)) { + rv = EINVAL; xbps_dbg_printf(xhp, "xbps_transaction_store failed for `%s': %s\n", reqpkg, strerror(rv)); break; } } xbps_object_iterator_release(iter); +out: (*depth)--; return rv; } int HIDDEN -xbps_repository_find_deps(struct xbps_handle *xhp, - xbps_array_t unsorted, - xbps_dictionary_t repo_pkgd) +xbps_transaction_pkg_deps(struct xbps_handle *xhp, + xbps_array_t pkgs, + xbps_dictionary_t pkg_repod) { - xbps_array_t pkg_rdeps, pkg_provides = NULL; const char *pkgver; unsigned short depth = 0; - pkg_rdeps = xbps_dictionary_get(repo_pkgd, "run_depends"); - if (xbps_array_count(pkg_rdeps) == 0) - return 0; + assert(xhp); + assert(pkgs); + assert(pkg_repod); - xbps_dictionary_get_cstring_nocopy(repo_pkgd, "pkgver", &pkgver); + xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver); xbps_dbg_printf(xhp, "Finding required dependencies for '%s':\n", pkgver); /* * This will find direct and indirect deps, if any of them is not * there it will be added into the missing_deps array. */ - pkg_provides = xbps_dictionary_get(repo_pkgd, "provides"); - return find_repo_deps(xhp, unsorted, pkg_rdeps, pkg_provides, pkgver, &depth); + return repo_deps(xhp, pkgs, pkg_repod, &depth); } diff --git a/lib/transaction_prepare.c b/lib/transaction_prepare.c index 5b7b411e..81a74f9a 100644 --- a/lib/transaction_prepare.c +++ b/lib/transaction_prepare.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2015 Juan Romero Pardines. + * Copyright (c) 2009-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,16 +71,18 @@ compute_transaction_stats(struct xbps_handle *xhp) return EINVAL; while ((obj = xbps_object_iterator_next(iter)) != NULL) { - const char *pkgver = NULL, *repo = NULL, *tract = NULL; + const char *pkgver = NULL, *repo = NULL, *pkgname = NULL; bool preserve = false; + xbps_trans_type_t ttype; /* * Count number of pkgs to be removed, configured, * installed and updated. */ xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract); + xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgname); xbps_dictionary_get_cstring_nocopy(obj, "repository", &repo); xbps_dictionary_get_bool(obj, "preserve", &preserve); + ttype = xbps_transaction_pkg_type(obj); if (xbps_repository_is_remote(repo) && !xbps_binpkg_exists(xhp, obj)) { xbps_dictionary_get_uint64(obj, "filename-size", &tsize); @@ -93,33 +95,28 @@ compute_transaction_stats(struct xbps_handle *xhp) continue; } - if (strcmp(tract, "configure") == 0) { + if (ttype == XBPS_TRANS_CONFIGURE) { cf_pkgcnt++; continue; - } else if (strcmp(tract, "install") == 0) { + } else if (ttype == XBPS_TRANS_INSTALL) { inst_pkgcnt++; - } else if (strcmp(tract, "update") == 0) { + } else if (ttype == XBPS_TRANS_UPDATE) { up_pkgcnt++; - } else if (strcmp(tract, "remove") == 0) { + } else if (ttype == XBPS_TRANS_REMOVE) { rm_pkgcnt++; } - if ((strcmp(tract, "install") == 0) || (strcmp(tract, "update") == 0)) { + if (ttype == XBPS_TRANS_INSTALL || ttype == XBPS_TRANS_UPDATE) { /* installed_size from repo */ xbps_dictionary_get_uint64(obj, "installed_size", &tsize); instsize += tsize; } /* - * If removing or updating a package, get installed_size - * from pkgdb instead. + * If removing or updating a package without preserve, + * get installed_size from pkgdb instead. */ - if ((strcmp(tract, "remove") == 0) || - ((strcmp(tract, "update") == 0) && !preserve)) { - char pkgname[XBPS_NAME_SIZE]; - - if (!xbps_pkg_name(pkgname, XBPS_NAME_SIZE, pkgver)) { - abort(); - } + if (ttype == XBPS_TRANS_REMOVE || + ((ttype == XBPS_TRANS_UPDATE) && !preserve)) { pkg_metad = xbps_pkgdb_get_pkg(xhp, pkgname); if (pkg_metad == NULL) continue; @@ -273,8 +270,9 @@ xbps_transaction_init(struct xbps_handle *xhp) int xbps_transaction_prepare(struct xbps_handle *xhp) { - xbps_array_t array, pkgs, edges; + xbps_array_t pkgs, edges; xbps_dictionary_t tpkgd; + xbps_trans_type_t ttype; unsigned int i, cnt; int rv = 0; bool all_on_hold = true; @@ -290,6 +288,8 @@ xbps_transaction_prepare(struct xbps_handle *xhp) */ if ((edges = xbps_array_create()) == NULL) return ENOMEM; + + xbps_dbg_printf(xhp, "%s: processing deps\n", __func__); /* * The edges are also appended after its dependencies have been * collected; the edges at the original array are removed later. @@ -300,24 +300,28 @@ xbps_transaction_prepare(struct xbps_handle *xhp) for (i = 0; i < cnt; i++) { xbps_dictionary_t pkgd; xbps_string_t str; - const char *tract = NULL; pkgd = xbps_array_get(pkgs, i); str = xbps_dictionary_get(pkgd, "pkgver"); - xbps_dictionary_get_cstring_nocopy(pkgd, "transaction", &tract); - if ((strcmp(tract, "remove") == 0) || strcmp(tract, "hold") == 0) + ttype = xbps_transaction_pkg_type(pkgd); + + if (ttype == XBPS_TRANS_REMOVE || ttype == XBPS_TRANS_HOLD) continue; assert(xbps_object_type(str) == XBPS_TYPE_STRING); - if (!xbps_array_add(edges, str)) + if (!xbps_array_add(edges, str)) { + xbps_object_release(edges); return ENOMEM; - - if ((rv = xbps_repository_find_deps(xhp, pkgs, pkgd)) != 0) + } + if ((rv = xbps_transaction_pkg_deps(xhp, pkgs, pkgd)) != 0) { + xbps_object_release(edges); return rv; - - if (!xbps_array_add(pkgs, pkgd)) + } + if (!xbps_array_add(pkgs, pkgd)) { + xbps_object_release(edges); return ENOMEM; + } } /* ... remove dup edges at head */ for (i = 0; i < xbps_array_count(edges); i++) { @@ -338,13 +342,10 @@ xbps_transaction_prepare(struct xbps_handle *xhp) * If all pkgs in transaction are on hold, no need to check * for anything else. */ - all_on_hold = true; + xbps_dbg_printf(xhp, "%s: checking on hold pkgs\n", __func__); for (i = 0; i < cnt; i++) { - const char *action; - tpkgd = xbps_array_get(pkgs, i); - xbps_dictionary_get_cstring_nocopy(tpkgd, "transaction", &action); - if (strcmp(action, "hold")) { + if (xbps_transaction_pkg_type(tpkgd) != XBPS_TRANS_HOLD) { all_on_hold = false; break; } @@ -355,17 +356,22 @@ xbps_transaction_prepare(struct xbps_handle *xhp) /* * Check for packages to be replaced. */ - if ((rv = xbps_transaction_package_replace(xhp, pkgs)) != 0) { + xbps_dbg_printf(xhp, "%s: checking replaces\n", __func__); + if (!xbps_transaction_check_replaces(xhp, pkgs)) { xbps_object_release(xhp->transd); xhp->transd = NULL; - return rv; + return EINVAL; } /* - * If there are missing deps or revdeps bail out. + * Check if there are missing revdeps. */ - xbps_transaction_revdeps(xhp, pkgs); - array = xbps_dictionary_get(xhp->transd, "missing_deps"); - if (xbps_array_count(array)) { + xbps_dbg_printf(xhp, "%s: checking revdeps\n", __func__); + if (!xbps_transaction_check_revdeps(xhp, pkgs)) { + xbps_object_release(xhp->transd); + xhp->transd = NULL; + return EINVAL; + } + if (xbps_dictionary_get(xhp->transd, "missing_deps")) { if (xhp->flags & XBPS_FLAG_FORCE_REMOVE_REVDEPS) { xbps_dbg_printf(xhp, "[trans] continuing with broken reverse dependencies!"); } else { @@ -373,17 +379,27 @@ xbps_transaction_prepare(struct xbps_handle *xhp) } } /* - * If there are package conflicts bail out. + * Check for package conflicts. */ - xbps_transaction_conflicts(xhp, pkgs); - array = xbps_dictionary_get(xhp->transd, "conflicts"); - if (xbps_array_count(array)) + xbps_dbg_printf(xhp, "%s: checking conflicts\n", __func__); + if (!xbps_transaction_check_conflicts(xhp, pkgs)) { + xbps_object_release(xhp->transd); + xhp->transd = NULL; + return EINVAL; + } + if (xbps_dictionary_get(xhp->transd, "conflicts")) { return EAGAIN; + } /* * Check for unresolved shared libraries. */ - if (xbps_transaction_shlibs(xhp, pkgs, - xbps_dictionary_get(xhp->transd, "missing_shlibs"))) { + xbps_dbg_printf(xhp, "%s: checking shlibs\n", __func__); + if (!xbps_transaction_check_shlibs(xhp, pkgs)) { + xbps_object_release(xhp->transd); + xhp->transd = NULL; + return EINVAL; + } + if (xbps_dictionary_get(xhp->transd, "missing_shlibs")) { if (xhp->flags & XBPS_FLAG_FORCE_REMOVE_REVDEPS) { xbps_dbg_printf(xhp, "[trans] continuing with unresolved shared libraries!"); } else { @@ -396,15 +412,13 @@ out: * number of packages to be installed, updated, configured * and removed to the transaction dictionary. */ + xbps_dbg_printf(xhp, "%s: computing stats\n", __func__); if ((rv = compute_transaction_stats(xhp)) != 0) { return rv; } /* - * Remove now unneeded objects. + * Make transaction dictionary immutable. */ - 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); return 0; diff --git a/lib/transaction_store.c b/lib/transaction_store.c index ec249f07..bb4e4699 100644 --- a/lib/transaction_store.c +++ b/lib/transaction_store.c @@ -30,47 +30,50 @@ #include "xbps_api_impl.h" -int HIDDEN +bool HIDDEN xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs, - xbps_dictionary_t pkgrd, const char *tract, bool autoinst) + xbps_dictionary_t pkgrd, bool autoinst) { xbps_dictionary_t d, pkgd; xbps_array_t replaces; - const char *pkgver, *curpkgver, *repo; - char pkgname[XBPS_NAME_SIZE], *self_replaced; + const char *pkgver, *pkgname, *curpkgver, *repo; + char *self_replaced; int rv; + assert(xhp); + assert(pkgs); + assert(pkgrd); + if (!xbps_dictionary_get_cstring_nocopy(pkgrd, "pkgver", &pkgver)) { - abort(); + return false; } - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); + if (!xbps_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname)) { + return false; } - d = xbps_find_pkg_in_array(pkgs, pkgname, NULL); + d = xbps_find_pkg_in_array(pkgs, pkgname, 0); if (xbps_object_type(d) == XBPS_TYPE_DICTIONARY) { /* compare version stored in transaction vs current */ if (!xbps_dictionary_get_cstring_nocopy(d, "pkgver", &curpkgver)) { - abort(); + return false; } rv = xbps_cmpver(pkgver, curpkgver); if (rv == 0 || rv == -1) { /* same version or stored version greater than current */ - return 0; + return true; } else { /* * Current version is greater than stored, * replace stored with current. */ if (!xbps_remove_pkg_from_array_by_pkgver(pkgs, curpkgver)) { - abort(); + return false; } - xbps_dbg_printf(xhp, "[trans] replaced %s with %s\n", - curpkgver, pkgver); + xbps_dbg_printf(xhp, "[trans] replaced %s with %s\n", curpkgver, pkgver); } } if ((pkgd = xbps_dictionary_copy_mutable(pkgrd)) == NULL) - return ENOMEM; + return false; /* * Add required objects into package dep's dictionary. @@ -100,15 +103,13 @@ xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs, xbps_dictionary_get_cstring_nocopy(pkgd, "repository", &repo); xbps_set_cb_state(xhp, XBPS_STATE_TRANS_ADDPKG, 0, pkgver, - "Found %s (%s) in repository %s", pkgver, tract, repo); - - xbps_dbg_printf(xhp, "Added `%s' into the dependency list (%s)\n", - pkgver, repo); + "Found %s in repository %s", pkgver, repo); + xbps_dbg_printf(xhp, "[trans] `%s' stored (%s)\n", pkgver, repo); xbps_object_release(pkgd); - return 0; + return true; err: xbps_object_release(pkgd); - return EINVAL; + return false; } diff --git a/tests/xbps/libxbps/shell/hold_test.sh b/tests/xbps/libxbps/shell/hold_test.sh index f5627a7a..36fe3781 100644 --- a/tests/xbps/libxbps/shell/hold_test.sh +++ b/tests/xbps/libxbps/shell/hold_test.sh @@ -26,10 +26,6 @@ downgrade_hold_body() { xbps-rindex -d -a $PWD/*.xbps atf_check_equal $? 0 cd .. - out=$(xbps-install -r root --repository=$PWD/repo -un) - set -- $out - exp="$1 $2 $3 $4" - atf_check_equal "$exp" "A-0.1_1 hold noarch $PWD/repo" xbps-install -r root --repository=$PWD/repo -yuvd atf_check_equal $? 0 out=$(xbps-query -r root -p pkgver A) diff --git a/tests/xbps/libxbps/shell/update_hold_test.sh b/tests/xbps/libxbps/shell/update_hold_test.sh index 06ee07b2..dc689427 100644 --- a/tests/xbps/libxbps/shell/update_hold_test.sh +++ b/tests/xbps/libxbps/shell/update_hold_test.sh @@ -26,10 +26,6 @@ update_hold_body() { xbps-rindex -d -a $PWD/*.xbps atf_check_equal $? 0 cd .. - out=$(xbps-install -r root --repository=$PWD/repo -un) - set -- $out - exp="$1 $2 $3 $4" - atf_check_equal "$exp" "A-1.1_1 hold noarch $PWD/repo" xbps-install -r root --repository=$PWD/repo -yuvd atf_check_equal $? 0 out=$(xbps-query -r root -p pkgver A)