diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index aac5b11b5..c3525be8d 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -54,6 +54,19 @@ struct archive_entry; +enum xbps_file_flag { + XBPS_FILE_CONF = 1 << 0, + XBPS_FILE_ALTERNATIVE = 1 << 1, +}; + +struct xbps_file { + char *path; + uint64_t size; + enum xbps_file_flag flags; + char *sha256; + const char *target; +}; + /** * @private */ @@ -71,10 +84,6 @@ bool HIDDEN xbps_remove_pkg_from_array_by_pkgver(xbps_array_t, const char *); void HIDDEN xbps_fetch_set_cache_connection(int, int); void HIDDEN xbps_fetch_unset_cache_connection(void); int HIDDEN xbps_cb_message(struct xbps_handle *, xbps_dictionary_t, const char *); -int HIDDEN xbps_entry_is_a_conf_file(xbps_dictionary_t, const char *); -int HIDDEN xbps_entry_install_conf_file(struct xbps_handle *, xbps_dictionary_t, - xbps_dictionary_t, struct archive_entry *, const char *, - const char *, bool); 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 *); @@ -94,6 +103,9 @@ bool HIDDEN xbps_transaction_store(struct xbps_handle *, xbps_array_t, xbps_dict int HIDDEN xbps_transaction_init(struct xbps_handle *); int HIDDEN xbps_transaction_files(struct xbps_handle *, xbps_object_iterator_t); +void HIDDEN xbps_transaction_files_free(struct xbps_handle *); +int HIDDEN xbps_transaction_file_get(struct xbps_handle *xhp, const char *path, + const struct xbps_file **oldp, const struct xbps_file **newp); 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); @@ -101,8 +113,6 @@ int HIDDEN xbps_transaction_internalize(struct xbps_handle *, xbps_object_iterat 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 *, - xbps_dictionary_t, const char *, const char *); int HIDDEN xbps_file_exec(struct xbps_handle *, const char *, ...); void HIDDEN xbps_set_cb_fetch(struct xbps_handle *, off_t, off_t, off_t, const char *, bool, bool, bool); diff --git a/lib/Makefile b/lib/Makefile index 0cf6ac84f..84489e7f4 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -35,7 +35,7 @@ LIBFETCH_GEN = fetch/ftperr.h fetch/httperr.h EXTOBJS = external/dewey.o external/fexec.o external/mkpath.o # libxbps -OBJS = package_configure.o package_config_files.o package_orphans.o +OBJS = package_configure.o package_orphans.o OBJS += package_remove.o package_state.o package_msg.o OBJS += package_unpack.o package_register.o package_script.o verifysig.o OBJS += transaction_commit.o transaction_prepare.o diff --git a/lib/package_config_files.c b/lib/package_config_files.c deleted file mode 100644 index ea0898669..000000000 --- a/lib/package_config_files.c +++ /dev/null @@ -1,248 +0,0 @@ -/*- - * Copyright (c) 2009-2014 Juan Romero Pardines. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include - -#include - -#include "xbps_api_impl.h" - -/* - * Returns true if entry is a configuration file, false otherwise. - */ -int HIDDEN -xbps_entry_is_a_conf_file(xbps_dictionary_t filesd, - const char *entry_pname) -{ - xbps_array_t array; - xbps_dictionary_t d; - const char *cffile; - - array = xbps_dictionary_get(filesd, "conf_files"); - if (xbps_array_count(array) == 0) - return false; - - for (unsigned int i = 0; i < xbps_array_count(array); i++) { - d = xbps_array_get(array, i); - xbps_dictionary_get_cstring_nocopy(d, "file", &cffile); - if (strcmp(cffile, entry_pname) == 0) - return true; - } - return false; -} - -/* - * Returns 1 if entry should be installed, 0 if don't or -1 on error. - */ -int HIDDEN -xbps_entry_install_conf_file(struct xbps_handle *xhp, - xbps_dictionary_t binpkg_filesd, - xbps_dictionary_t pkg_filesd, - struct archive_entry *entry, - const char *entry_pname, - const char *pkgver, - bool mysymlink) -{ - xbps_object_t obj, obj2; - xbps_object_iterator_t iter, iter2; - const char *version = NULL, *cffile, *sha256_new = NULL; - char buf[PATH_MAX], sha256_cur[XBPS_SHA256_SIZE]; - const char *sha256_orig = NULL; - int rv = 0; - - assert(xbps_object_type(binpkg_filesd) == XBPS_TYPE_DICTIONARY); - assert(entry); - assert(entry_pname); - assert(pkgver); - - iter = xbps_array_iter_from_dict(binpkg_filesd, "conf_files"); - if (iter == NULL) - return -1; - - /* - * Get original hash for the file from current - * installed package. - */ - xbps_dbg_printf("%s: processing conf_file %s\n", - pkgver, entry_pname); - - if (pkg_filesd == NULL || mysymlink) { - /* - * 1. File exists on disk but it's not managed by the same package. - * 2. File exists on disk as symlink. - * Install it as file.new-. - */ - version = xbps_pkg_version(pkgver); - assert(version); - xbps_dbg_printf("%s: conf_file %s not currently " - "installed, renaming to %s.new-%s\n", pkgver, - entry_pname, entry_pname, version); - snprintf(buf, sizeof(buf), "%s.new-%s", entry_pname, version); - xbps_set_cb_state(xhp, XBPS_STATE_CONFIG_FILE, - 0, pkgver, "File `%s' exists, installing configuration file to `%s'.", entry_pname, buf); - archive_entry_copy_pathname(entry, buf); - rv = 1; - goto out; - } - - iter2 = xbps_array_iter_from_dict(pkg_filesd, "conf_files"); - if (iter2 != NULL) { - while ((obj2 = xbps_object_iterator_next(iter2))) { - xbps_dictionary_get_cstring_nocopy(obj2, - "file", &cffile); - snprintf(buf, sizeof(buf), ".%s", cffile); - if (strcmp(entry_pname, buf) == 0) { - xbps_dictionary_get_cstring_nocopy(obj2, "sha256", &sha256_orig); - break; - } - } - xbps_object_iterator_release(iter2); - } - /* - * First case: original hash not found, install new file. - */ - if (sha256_orig == NULL) { - xbps_dbg_printf("%s: conf_file %s not installed\n", - pkgver, entry_pname); - rv = 1; - goto out; - } - - /* - * Compare original, installed and new hash for current file. - */ - while ((obj = xbps_object_iterator_next(iter))) { - xbps_dictionary_get_cstring_nocopy(obj, "file", &cffile); - snprintf(buf, sizeof(buf), ".%s", cffile); - if (strcmp(entry_pname, buf)) { - continue; - } - if (!xbps_file_sha256(sha256_cur, sizeof sha256_cur, buf)) { - if (errno == ENOENT) { - /* - * File not installed, install new one. - */ - xbps_dbg_printf("%s: conf_file %s not " - "installed\n", pkgver, entry_pname); - rv = 1; - break; - } else { - rv = -1; - break; - } - } - xbps_dictionary_get_cstring_nocopy(obj, "sha256", &sha256_new); - /* - * Orig = X, Curr = X, New = X - * - * Keep file as is (no changes). - */ - if ((strcmp(sha256_orig, sha256_cur) == 0) && - (strcmp(sha256_orig, sha256_new) == 0) && - (strcmp(sha256_cur, sha256_new) == 0)) { - xbps_dbg_printf("%s: conf_file %s orig = X, " - "cur = X, new = X\n", pkgver, entry_pname); - rv = 0; - break; - /* - * Orig = X, Curr = X, New = Y - * - * Install new file (installed file hasn't been modified) if - * configuration option keepconfig is NOT set. - */ - } else if ((strcmp(sha256_orig, sha256_cur) == 0) && - (strcmp(sha256_orig, sha256_new)) && - (strcmp(sha256_cur, sha256_new)) && - (!(xhp->flags & XBPS_FLAG_KEEP_CONFIG))) { - xbps_set_cb_state(xhp, XBPS_STATE_CONFIG_FILE, - 0, pkgver, - "Updating configuration file `%s' provided " - "by `%s'.", cffile, pkgver); - rv = 1; - break; - /* - * Orig = X, Curr = Y, New = X - * - * Keep installed file as is because it has been modified, - * but new package doesn't contain new changes compared - * to the original version. - */ - } else if ((strcmp(sha256_orig, sha256_new) == 0) && - (strcmp(sha256_cur, sha256_new)) && - (strcmp(sha256_orig, sha256_cur))) { - xbps_set_cb_state(xhp, XBPS_STATE_CONFIG_FILE, - 0, pkgver, - "Keeping modified configuration file `%s'.", - cffile); - rv = 0; - break; - /* - * Orig = X, Curr = Y, New = Y - * - * Keep file as is because changes made are compatible - * with new version. - */ - } else if ((strcmp(sha256_cur, sha256_new) == 0) && - (strcmp(sha256_orig, sha256_new)) && - (strcmp(sha256_orig, sha256_cur))) { - xbps_dbg_printf("%s: conf_file %s orig = X, " - "cur = Y, new = Y\n", pkgver, entry_pname); - rv = 0; - break; - /* - * Orig = X, Curr = Y, New = Z - * or - * Orig = X, Curr = X, New = Y if keepconf is set - * - * Install new file as .new- - */ - } else if (((strcmp(sha256_orig, sha256_cur)) && - (strcmp(sha256_cur, sha256_new)) && - (strcmp(sha256_orig, sha256_new))) || - (xhp->flags & XBPS_FLAG_KEEP_CONFIG)) { - version = xbps_pkg_version(pkgver); - assert(version); - snprintf(buf, sizeof(buf), ".%s.new-%s", cffile, version); - xbps_set_cb_state(xhp, XBPS_STATE_CONFIG_FILE, - 0, pkgver, "File `%s' exists, installing configuration file to `%s'.", cffile, buf); - archive_entry_copy_pathname(entry, buf); - rv = 1; - break; - } - } - -out: - - xbps_object_iterator_release(iter); - - xbps_dbg_printf("%s: conf_file %s returned %d\n", - pkgver, entry_pname, rv); - - return rv; -} diff --git a/lib/package_unpack.c b/lib/package_unpack.c index d3b98fce6..5c890117e 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2008-2015 Juan Romero Pardines. + * Copyright (c) 2024 Duncan Overbruck . * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -79,6 +80,87 @@ match_preserved_file(struct xbps_handle *xhp, const char *entry) return xbps_match_string_in_array(xhp->preserved_files, file); } +enum { + CONFFILE_SKIP = 0, + CONFFILE_UPDATE = 1, + CONFFILE_NEW = 2, +}; + +static int +handle_conffile(struct xbps_handle *xhp, + const char *path, + const struct xbps_file *old, + const struct xbps_file *new, + const struct stat *st) +{ + char sha256_cur[XBPS_SHA256_SIZE]; + enum { + MATCH_SAME = 1 << 0, + MATCH_OLD = 1 << 1, + MATCH_NEW = 1 << 2, + } match = 0; + + (void) xhp; + + /* 1. File exist on disk, but was untracked, extract as new. */ + if (!old) + return CONFFILE_NEW; + + /* 2. File exists as link, extract as new. */ + if (S_ISLNK(st->st_mode)) + return CONFFILE_NEW; + + if (!xbps_file_sha256(sha256_cur, sizeof(sha256_cur), path)) { + if (errno == ENOENT) + return 0; + return -errno; + } + + if (old && strcmp(old->sha256, new->sha256) == 0) + match |= MATCH_SAME; + if (old && strcmp(sha256_cur, old->sha256) == 0) + match |= MATCH_OLD; + if (strcmp(sha256_cur, new->sha256) == 0) + match |= MATCH_NEW; + + if (match == (MATCH_SAME|MATCH_OLD|MATCH_NEW)) { + /* + * All files are the same, do nothing. + */ + return CONFFILE_SKIP; + } else if (match == MATCH_SAME) { + /* + * Old and new package files are the same, + * but on disk differs, extract as new. + */ + return CONFFILE_NEW; + } else if (match == MATCH_NEW) { + /* + * File matches the new config file, do nothing. + */ + return CONFFILE_SKIP; + } else if (match == MATCH_OLD) { + /* + * File matches the old config file: + * If keep_conf is on, extract as new, otherwise + * update the file. + */ + if (xhp->flags & XBPS_FLAG_KEEP_CONFIG) + return CONFFILE_NEW; + return CONFFILE_UPDATE; + } else if (match == 0) { + /* + * Old and new file changes and on disk is also differnt, + * extract as new. + */ + return CONFFILE_NEW; + } else { + return -EINVAL; + } + + return 0; +} + static int unpack_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod, @@ -86,7 +168,9 @@ unpack_archive(struct xbps_handle *xhp, const char *fname, struct archive *ar) { - xbps_dictionary_t binpkg_filesd, pkg_filesd, obsd; + char buf[PATH_MAX]; + const struct xbps_file *old = NULL, *new = NULL; + xbps_dictionary_t binpkg_filesd, obsd; xbps_array_t array, obsoletes; xbps_trans_type_t ttype; const struct stat *entry_statp; @@ -95,13 +179,12 @@ unpack_archive(struct xbps_handle *xhp, struct archive_entry *entry; ssize_t entry_size; const char *entry_pname, *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; uid_t euid; - binpkg_filesd = pkg_filesd = NULL; + binpkg_filesd = NULL; force = preserve = update = file_exists = false; xucd_stats = false; ar_rv = rv = error = entry_type = flags = 0; @@ -132,19 +215,19 @@ unpack_archive(struct xbps_handle *xhp, xbps_dictionary_get_dict(xhp->transd, "obsolete_files", &obsd) && (obsoletes = xbps_dictionary_get(obsd, pkgname))) { for (unsigned int i = 0; i < xbps_array_count(obsoletes); i++) { - const char *file = NULL; - xbps_array_get_cstring_nocopy(obsoletes, i, &file); - if (remove(file) == -1) { + const char *path = NULL; + xbps_array_get_cstring_nocopy(obsoletes, i, &path); + if (remove(path) == -1) { xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FILE_OBSOLETE_FAIL, errno, pkgver, "%s: failed to remove obsolete entry `%s': %s", - pkgver, file, strerror(errno)); + pkgver, path, strerror(errno)); continue; } xbps_set_cb_state(xhp, XBPS_STATE_REMOVE_FILE_OBSOLETE, - 0, pkgver, "%s: removed obsolete entry: %s", pkgver, file); + 0, pkgver, "%s: removed obsolete entry: %s", pkgver, path); } } @@ -206,11 +289,6 @@ unpack_archive(struct xbps_handle *xhp, goto out; } - /* - * Internalize current pkg metadata files plist. - */ - pkg_filesd = xbps_pkgdb_get_pkg_files(xhp, pkgname); - /* * Unpack all files on archive now. */ @@ -291,15 +369,19 @@ unpack_archive(struct xbps_handle *xhp, continue; } + rv = xbps_transaction_file_get(xhp, entry_pname+1, &old, &new); + if (rv < 0) { + xbps_error_printf("unknown file in binary package: %s: %s\n", + pkgver, entry_pname+1); + rv = -rv; + goto out; + } + /* * Check if current entry is a configuration file, * that should be kept. */ - if (!force && (entry_type == AE_IFREG)) { - buf = strchr(entry_pname, '.') + 1; - assert(buf != NULL); - keep_conf_file = xbps_entry_is_a_conf_file(binpkg_filesd, buf); - } + keep_conf_file = (new->flags & XBPS_FILE_CONF) != 0; /* * If file to be extracted does not match the file type of @@ -322,22 +404,42 @@ unpack_archive(struct xbps_handle *xhp, if (xhp->unpack_cb != NULL) xucd.entry_is_conf = true; - rv = xbps_entry_install_conf_file(xhp, - binpkg_filesd, pkg_filesd, entry, - entry_pname, pkgver, S_ISLNK(st.st_mode)); - if (rv == -1) { + rv = handle_conffile(xhp, entry_pname, old, new, &st); + if (rv < 0) { /* error */ + rv = -rv; goto out; - } else if (rv == 0) { + } else if (rv == CONFFILE_SKIP) { /* * Keep curfile as is. */ skip_extract = true; + } else if (rv == CONFFILE_UPDATE) { + /* + * Update file. + */ + } else if (rv == CONFFILE_NEW) { + /* + * Extract as .new-$version. + */ + const char *version = xbps_pkg_version(pkgver); + snprintf(buf, sizeof(buf), "%s.new-%s", + entry_pname, version); + xbps_set_cb_state(xhp, XBPS_STATE_CONFIG_FILE, + 0, pkgver, "File `%s' exists," + " installing configuration file" + " to `%s'.", entry_pname+1, buf+1); + archive_entry_copy_pathname(entry, buf); } rv = 0; } else { - rv = xbps_file_hash_check_dictionary( - xhp, binpkg_filesd, "files", buf); + if (!new->sha256) { + xbps_error_printf("missing checksum in binary package" + ": %s: %s\n", pkgver, entry_pname+1); + rv = EINVAL; + goto out; + } + rv = xbps_file_sha256_check(entry_pname, new->sha256); if (rv == -1) { /* error */ xbps_dbg_printf( @@ -450,27 +552,24 @@ unpack_archive(struct xbps_handle *xhp, if (xbps_dictionary_count(binpkg_filesd)) { mode_t prev_umask; prev_umask = umask(022); - buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); + snprintf(buf, sizeof(buf), "%s/.%s-files.plist", xhp->metadir, pkgname); if (!xbps_dictionary_externalize_to_file(binpkg_filesd, buf)) { rv = errno; umask(prev_umask); - free(buf); xbps_set_cb_state(xhp, XBPS_STATE_UNPACK_FAIL, rv, pkgver, "%s: [unpack] failed to externalize pkg " "pkg metadata files: %s", pkgver, strerror(rv)); goto out; } umask(prev_umask); - free(buf); } out: /* * If unpacked pkg has no files, remove its files metadata plist. */ if (!xbps_dictionary_count(binpkg_filesd)) { - buf = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname); + snprintf(buf, sizeof(buf), "%s/.%s-files.plist", xhp->metadir, pkgname); unlink(buf); - free(buf); } xbps_object_release(binpkg_filesd); diff --git a/lib/transaction_commit.c b/lib/transaction_commit.c index ddd0141e4..cd5d76c98 100644 --- a/lib/transaction_commit.c +++ b/lib/transaction_commit.c @@ -436,6 +436,7 @@ xbps_transaction_commit(struct xbps_handle *xhp) out: xbps_object_release(remove_scripts); xbps_object_iterator_release(iter); + xbps_transaction_files_free(xhp); if (rv == 0) { /* Force a pkgdb write for all unpacked pkgs in transaction */ rv = xbps_pkgdb_update(xhp, true, true); diff --git a/lib/transaction_files.c b/lib/transaction_files.c index 890b447ab..1de296bd0 100644 --- a/lib/transaction_files.c +++ b/lib/transaction_files.c @@ -48,11 +48,9 @@ struct item { char *file; size_t len; struct { + struct xbps_file file; const char *pkgname; const char *pkgver; - char *sha256; - const char *target; - uint64_t size; enum type type; /* index is the index of the package update/install/removal in the transaction * and is used to decide which package should remove the given file or dir */ @@ -311,8 +309,8 @@ collect_obsoletes(struct xbps_handle *xhp) /* * Skip unexisting files and keep files with hash mismatch. */ - if (item->old.sha256 != NULL) { - rv = xbps_file_sha256_check(item->file, item->old.sha256); + if (item->old.file.sha256 != NULL) { + rv = xbps_file_sha256_check(item->file, item->old.file.sha256); switch (rv) { case 0: /* hash matches, we can safely delete and/or overwrite it */ @@ -361,16 +359,16 @@ collect_obsoletes(struct xbps_handle *xhp) xhp->rootdir, item->file+1); file = path; } - lnk = xbps_symlink_target(xhp, file, item->old.target); + lnk = xbps_symlink_target(xhp, file, item->old.file.target); if (lnk == NULL) { xbps_dbg_printf("[obsoletes] %s " "symlink_target: %s\n", item->file+1, strerror(errno)); continue; } - if (strcmp(lnk, item->old.target) != 0) { + if (strcmp(lnk, item->old.file.target) != 0) { xbps_dbg_printf("[obsoletes] %s: skipping modified" " symlink (stored `%s' current `%s'): %s\n", - item->old.pkgname, item->old.target, lnk, item->file+1); + item->old.pkgname, item->old.file.target, lnk, item->file+1); free(lnk); continue; } @@ -523,24 +521,36 @@ collect_file(struct xbps_handle *xhp, const char *file, size_t size, item->old.pkgname = pkgname; item->old.pkgver = pkgver; item->old.type = type; - item->old.size = size; + item->old.file.size = size; item->old.index = idx; item->old.preserve = preserve; item->old.update = update; item->old.removepkg = removepkg; - item->old.target = target; - if (sha256) - item->old.sha256 = strdup(sha256); + item->old.file.target = target; + if (sha256) { + item->old.file.sha256 = strdup(sha256); + if (!item->old.file.sha256) + return errno; + } + if (type == TYPE_CONFFILE) + item->old.file.flags |= XBPS_FILE_CONF; } else { item->new.pkgname = pkgname; item->new.pkgver = pkgver; item->new.type = type; - item->new.size = size; + item->new.file.size = size; item->new.index = idx; item->new.preserve = preserve; item->new.update = update; item->new.removepkg = removepkg; - item->new.target = target; + item->new.file.target = target; + if (sha256) { + item->new.file.sha256 = strdup(sha256); + if (!item->new.file.sha256) + return errno; + } + if (type == TYPE_CONFFILE) + item->new.file.flags |= XBPS_FILE_CONF; } if (item->old.type && item->new.type) { /* @@ -580,8 +590,7 @@ collect_files(struct xbps_handle *xhp, xbps_dictionary_t d, for (i = 0; i < xbps_array_count(a); i++) { filed = xbps_array_get(a, i); xbps_dictionary_get_cstring_nocopy(filed, "file", &file); - if (removefile) - xbps_dictionary_get_cstring_nocopy(filed, "sha256", &sha256); + xbps_dictionary_get_cstring_nocopy(filed, "sha256", &sha256); size = 0; xbps_dictionary_get_uint64(filed, "size", &size); rv = collect_file(xhp, file, size, pkgname, pkgver, idx, sha256, @@ -600,8 +609,7 @@ collect_files(struct xbps_handle *xhp, xbps_dictionary_t d, xbps_dictionary_get_cstring_nocopy(filed, "file", &file); size = 0; xbps_dictionary_get_uint64(filed, "size", &size); - if (removefile) - xbps_dictionary_get_cstring_nocopy(filed, "sha256", &sha256); + xbps_dictionary_get_cstring_nocopy(filed, "sha256", &sha256); #if 0 /* XXX: how to handle conf_file size */ if (removefile && stat(file, &st) != -1 && size != (uint64_t)st.st_size) @@ -761,21 +769,6 @@ pathcmp(const void *l1, const void *l2) return (a->len < b->len) - (b->len < a->len); } -static void -cleanup(void) -{ - struct item *item, *itmp; - - HASH_ITER(hh, hashtab, item, itmp) { - HASH_DEL(hashtab, item); - free(item->file); - free(item->old.sha256); - free(item->new.sha256); - free(item); - } - free(items); -} - /* * xbps_transaction_files: * @@ -890,6 +883,37 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter) return rv; rv = collect_obsoletes(xhp); - cleanup(); return rv; } + +void HIDDEN +xbps_transaction_files_free(struct xbps_handle *xhp UNUSED) +{ + struct item *item, *itmp; + + HASH_ITER(hh, hashtab, item, itmp) { + HASH_DEL(hashtab, item); + free(item->file); + free(item->old.file.sha256); + free(item->new.file.sha256); + free(item); + } + free(items); +} + +int HIDDEN +xbps_transaction_file_get(struct xbps_handle *xhp UNUSED, const char *path, + const struct xbps_file **oldp, + const struct xbps_file **newp) +{ + struct item *item; + + item = lookupItem(path); + if (!item) + return -ENOENT; + if (oldp) + *oldp = item->old.pkgver ? &item->old.file : NULL; + if (newp) + *newp = item->new.pkgver ? &item->new.file : NULL; + return 0; +} diff --git a/lib/util_hash.c b/lib/util_hash.c index 3ed38c523..0f7bf629c 100644 --- a/lib/util_hash.c +++ b/lib/util_hash.c @@ -213,72 +213,3 @@ xbps_file_sha256_check(const char *file, const char *sha256) return 0; } - -static const char * -file_hash_dictionary(xbps_dictionary_t d, const char *key, const char *file) -{ - xbps_object_t obj; - xbps_object_iterator_t iter; - const char *curfile = NULL, *sha256 = NULL; - - assert(xbps_object_type(d) == XBPS_TYPE_DICTIONARY); - assert(key != NULL); - assert(file != NULL); - - iter = xbps_array_iter_from_dict(d, key); - if (iter == NULL) { - errno = ENOENT; - return NULL; - } - while ((obj = xbps_object_iterator_next(iter)) != NULL) { - xbps_dictionary_get_cstring_nocopy(obj, - "file", &curfile); - if (strcmp(file, curfile) == 0) { - /* file matched */ - xbps_dictionary_get_cstring_nocopy(obj, - "sha256", &sha256); - break; - } - } - xbps_object_iterator_release(iter); - if (sha256 == NULL) - errno = ENOENT; - - return sha256; -} - -int HIDDEN -xbps_file_hash_check_dictionary(struct xbps_handle *xhp, - xbps_dictionary_t d, - const char *key, - const char *file) -{ - const char *sha256d = NULL; - char *buf; - int rv; - - assert(xbps_object_type(d) == XBPS_TYPE_DICTIONARY); - assert(key != NULL); - assert(file != NULL); - - if ((sha256d = file_hash_dictionary(d, key, file)) == NULL) { - if (errno == ENOENT) - return 1; /* no match, file not found */ - - return -1; /* error */ - } - - if (strcmp(xhp->rootdir, "/") == 0) { - rv = xbps_file_sha256_check(file, sha256d); - } else { - buf = xbps_xasprintf("%s/%s", xhp->rootdir, file); - rv = xbps_file_sha256_check(buf, sha256d); - free(buf); - } - if (rv == 0) - return 0; /* matched */ - else if (rv == ERANGE || rv == ENOENT) - return 1; /* no match */ - else - return -1; /* error */ -}