From aa670a2517e0845c92115d41409bab2ec26abd88 Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Wed, 10 Jan 2024 19:38:52 +0100 Subject: [PATCH 1/8] lib: add xbps_transaction_file_get --- include/xbps_api_impl.h | 6 ++++ lib/transaction_commit.c | 1 + lib/transaction_files.c | 66 +++++++++++++++++++++++++--------------- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index aac5b11b5..63fa7d172 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -54,6 +54,10 @@ struct archive_entry; +struct xbps_file { + char *sha256; +}; + /** * @private */ @@ -94,6 +98,8 @@ 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 *); +const struct xbps_file HIDDEN *xbps_transaction_file_get(struct xbps_handle *xhp, const char *path); 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); 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..45c584893 100644 --- a/lib/transaction_files.c +++ b/lib/transaction_files.c @@ -48,9 +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; @@ -311,8 +311,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 */ @@ -529,8 +529,11 @@ collect_file(struct xbps_handle *xhp, const char *file, size_t size, item->old.update = update; item->old.removepkg = removepkg; item->old.target = target; - if (sha256) - item->old.sha256 = strdup(sha256); + if (sha256) { + item->old.file.sha256 = strdup(sha256); + if (!item->old.file.sha256) + return errno; + } } else { item->new.pkgname = pkgname; item->new.pkgver = pkgver; @@ -541,6 +544,11 @@ collect_file(struct xbps_handle *xhp, const char *file, size_t size, item->new.update = update; item->new.removepkg = removepkg; item->new.target = target; + if (sha256) { + item->new.file.sha256 = strdup(sha256); + if (!item->new.file.sha256) + return errno; + } } if (item->old.type && item->new.type) { /* @@ -580,8 +588,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 +607,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 +767,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 +881,31 @@ 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); +} + +const struct xbps_file HIDDEN * +xbps_transaction_file_get(struct xbps_handle *xhp UNUSED, const char *path) +{ + struct item *item; + + item = lookupItem(path); + if (!item) + return NULL; + return &item->new.file; +} From 33e81e7162d92ca22a12dba0af72ba6165ede70a Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Wed, 10 Jan 2024 19:39:23 +0100 Subject: [PATCH 2/8] lib: use xbps_transaction_file_get --- lib/package_unpack.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/package_unpack.c b/lib/package_unpack.c index d3b98fce6..c0b5ac449 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -86,6 +86,7 @@ unpack_archive(struct xbps_handle *xhp, const char *fname, struct archive *ar) { + const struct xbps_file *file; xbps_dictionary_t binpkg_filesd, pkg_filesd, obsd; xbps_array_t array, obsoletes; xbps_trans_type_t ttype; @@ -132,19 +133,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); } } @@ -291,6 +292,14 @@ unpack_archive(struct xbps_handle *xhp, continue; } + file = xbps_transaction_file_get(xhp, entry_pname+1); + if (!file) { + xbps_error_printf("unknown file in binary package: %s: %s\n", + pkgver, entry_pname+1); + rv = EINVAL; + goto out; + } + /* * Check if current entry is a configuration file, * that should be kept. @@ -336,8 +345,13 @@ unpack_archive(struct xbps_handle *xhp, } rv = 0; } else { - rv = xbps_file_hash_check_dictionary( - xhp, binpkg_filesd, "files", buf); + if (!file->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, file->sha256); if (rv == -1) { /* error */ xbps_dbg_printf( From f231641b94d35a32c071d24cbfc3b523032957d4 Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Wed, 10 Jan 2024 19:40:02 +0100 Subject: [PATCH 3/8] lib: remove xbps_file_hash_check_dictionary --- include/xbps_api_impl.h | 2 -- lib/util_hash.c | 69 ----------------------------------------- 2 files changed, 71 deletions(-) diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 63fa7d172..196f01dff 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -107,8 +107,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/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 */ -} From 2dedfd1ef6b978782036da7a022d4d87b6ca0228 Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Thu, 11 Jan 2024 15:34:06 +0100 Subject: [PATCH 4/8] lib: extend struct xbps_file to include a flag for conf files --- include/xbps_api_impl.h | 9 +++++++++ lib/transaction_files.c | 20 +++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 196f01dff..a93c6af11 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -54,8 +54,17 @@ 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; }; /** diff --git a/lib/transaction_files.c b/lib/transaction_files.c index 45c584893..d4bc565d8 100644 --- a/lib/transaction_files.c +++ b/lib/transaction_files.c @@ -51,8 +51,6 @@ struct item { struct xbps_file file; const char *pkgname; const char *pkgver; - 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 */ @@ -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,32 +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; + 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) { /* From b1831a663198410fa141ef441044a7ddfb3191d0 Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Thu, 11 Jan 2024 15:35:12 +0100 Subject: [PATCH 5/8] lib: replace xbps_entry_is_a_conf_file with XBPS_FILE_CONF flag --- include/xbps_api_impl.h | 1 - lib/package_config_files.c | 24 ------------------------ lib/package_unpack.c | 6 +----- 3 files changed, 1 insertion(+), 30 deletions(-) diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index a93c6af11..5b12398c0 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -84,7 +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); diff --git a/lib/package_config_files.c b/lib/package_config_files.c index ea0898669..a2b759c7f 100644 --- a/lib/package_config_files.c +++ b/lib/package_config_files.c @@ -33,30 +33,6 @@ #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. */ diff --git a/lib/package_unpack.c b/lib/package_unpack.c index c0b5ac449..e9cb86851 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -304,11 +304,7 @@ unpack_archive(struct xbps_handle *xhp, * 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 = (file->flags & XBPS_FILE_CONF) != 0; /* * If file to be extracted does not match the file type of From 91a63a147dbed404d54ca9945b278ac298fc3a8a Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Thu, 11 Jan 2024 17:03:34 +0100 Subject: [PATCH 6/8] lib: extend xbps_transaction_file_get to return old and new files --- include/xbps_api_impl.h | 3 ++- lib/package_unpack.c | 14 +++++++------- lib/transaction_files.c | 14 ++++++++++---- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 5b12398c0..0c73141d0 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -107,7 +107,8 @@ 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 *); -const struct xbps_file HIDDEN *xbps_transaction_file_get(struct xbps_handle *xhp, const char *path); +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); diff --git a/lib/package_unpack.c b/lib/package_unpack.c index e9cb86851..8687bb036 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -86,7 +86,7 @@ unpack_archive(struct xbps_handle *xhp, const char *fname, struct archive *ar) { - const struct xbps_file *file; + const struct xbps_file *old = NULL, *new = NULL; xbps_dictionary_t binpkg_filesd, pkg_filesd, obsd; xbps_array_t array, obsoletes; xbps_trans_type_t ttype; @@ -292,11 +292,11 @@ unpack_archive(struct xbps_handle *xhp, continue; } - file = xbps_transaction_file_get(xhp, entry_pname+1); - if (!file) { + 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 = EINVAL; + rv = -rv; goto out; } @@ -304,7 +304,7 @@ unpack_archive(struct xbps_handle *xhp, * Check if current entry is a configuration file, * that should be kept. */ - keep_conf_file = (file->flags & XBPS_FILE_CONF) != 0; + keep_conf_file = (new->flags & XBPS_FILE_CONF) != 0; /* * If file to be extracted does not match the file type of @@ -341,13 +341,13 @@ unpack_archive(struct xbps_handle *xhp, } rv = 0; } else { - if (!file->sha256) { + 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, file->sha256); + rv = xbps_file_sha256_check(entry_pname, new->sha256); if (rv == -1) { /* error */ xbps_dbg_printf( diff --git a/lib/transaction_files.c b/lib/transaction_files.c index d4bc565d8..1de296bd0 100644 --- a/lib/transaction_files.c +++ b/lib/transaction_files.c @@ -901,13 +901,19 @@ xbps_transaction_files_free(struct xbps_handle *xhp UNUSED) free(items); } -const struct xbps_file HIDDEN * -xbps_transaction_file_get(struct xbps_handle *xhp UNUSED, const char *path) +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 NULL; - return &item->new.file; + return -ENOENT; + if (oldp) + *oldp = item->old.pkgver ? &item->old.file : NULL; + if (newp) + *newp = item->new.pkgver ? &item->new.file : NULL; + return 0; } From 15f63745964fc1cc5f05a2b9b5982c7962547469 Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Thu, 11 Jan 2024 17:09:34 +0100 Subject: [PATCH 7/8] lib: clean rewrite of the configuration file handling --- lib/package_unpack.c | 125 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 107 insertions(+), 18 deletions(-) diff --git a/lib/package_unpack.c b/lib/package_unpack.c index 8687bb036..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,8 +168,9 @@ unpack_archive(struct xbps_handle *xhp, const char *fname, struct archive *ar) { + char buf[PATH_MAX]; const struct xbps_file *old = NULL, *new = NULL; - xbps_dictionary_t binpkg_filesd, pkg_filesd, obsd; + xbps_dictionary_t binpkg_filesd, obsd; xbps_array_t array, obsoletes; xbps_trans_type_t ttype; const struct stat *entry_statp; @@ -96,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; @@ -207,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. */ @@ -327,17 +404,32 @@ 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 { @@ -460,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); From 06981f1d8c3cc67c9e7d4b2491375cf1c29ce7cf Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Thu, 11 Jan 2024 17:13:11 +0100 Subject: [PATCH 8/8] lib: remove xbps_entry_install_conf_file --- include/xbps_api_impl.h | 3 - lib/Makefile | 2 +- lib/package_config_files.c | 224 ------------------------------------- 3 files changed, 1 insertion(+), 228 deletions(-) delete mode 100644 lib/package_config_files.c diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 0c73141d0..c3525be8d 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -84,9 +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_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 *); 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 a2b759c7f..000000000 --- a/lib/package_config_files.c +++ /dev/null @@ -1,224 +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 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; -}