From 8837e8c607f4058fbacc98fd636dde659a0e0346 Mon Sep 17 00:00:00 2001 From: Duncaen Date: Tue, 18 Jun 2019 13:49:24 +0200 Subject: [PATCH] lib/transaction_files.c: better handle preserve files --- lib/transaction_files.c | 59 +++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/lib/transaction_files.c b/lib/transaction_files.c index e5a2415d..61b24cc4 100644 --- a/lib/transaction_files.c +++ b/lib/transaction_files.c @@ -50,6 +50,8 @@ struct item { uint64_t size; enum type type; unsigned int index; + bool preserve; + bool update; } old, new; bool deleted; }; @@ -230,12 +232,18 @@ collect_obsoletes(struct xbps_handle *xhp) item = items[i]; - if (item->new.type == 0 && item->old.type != TYPE_DIR) { + + if (item->new.type == 0) { /* * File was removed and is not provided by any * new package. * Probably obsolete. */ + if (item->old.preserve && item->old.update) { + xbps_dbg_printf(xhp, "[files] %s: skipping `preserve` %s: %s\n", + item->old.pkgver, typestr(item->old.type), item->file); + continue; + } } else if (item->new.type == TYPE_CONFFILE) { /* * Ignore conf files. @@ -363,7 +371,8 @@ collect_obsoletes(struct xbps_handle *xhp) static int collect_file(struct xbps_handle *xhp, const char *file, size_t size, const char *pkgname, const char *pkgver, unsigned int idx, - const char *sha256, enum type type, bool remove) + const char *sha256, enum type type, bool update, bool preserve, + bool remove) { struct item *item; @@ -395,6 +404,22 @@ collect_file(struct xbps_handle *xhp, const char *file, size_t size, xbps_dbg_printf(xhp, "[files] %s: file already removed" " by package `%s': %s\n", pkgver, item->old.pkgver, file); + /* + * Check if `preserve` is violated. + */ + if (item->old.preserve && !preserve) { + xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, + EPERM, item->old.pkgver, + "%s: preserved file `%s' removed by %s.", + item->old.pkgver, file, pkgver); + return EPERM; + } else if (preserve && !item->old.preserve) { + xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, + EPERM, pkgver, + "%s: preserved file `%s' removed by %s.", + pkgver, file, item->old.pkgver); + return EPERM; + } return 0; } goto add; @@ -433,6 +458,8 @@ add: item->old.type = type; item->old.size = size; item->old.index = idx; + item->old.preserve = preserve; + item->old.update = update; if (sha256) item->old.sha256 = strdup(sha256); } else { @@ -441,6 +468,8 @@ add: item->new.type = type; item->new.size = size; item->new.index = idx; + item->new.preserve = preserve; + item->new.update = update; } if (item->old.type && item->new.type) { /* @@ -466,7 +495,7 @@ add: static int collect_files(struct xbps_handle *xhp, xbps_dictionary_t d, const char *pkgname, const char *pkgver, unsigned int idx, - bool remove) + bool update, bool preserve, bool remove) { xbps_array_t a; xbps_dictionary_t filed; @@ -484,7 +513,7 @@ collect_files(struct xbps_handle *xhp, xbps_dictionary_t d, size = 0; xbps_dictionary_get_uint64(filed, "size", &size); rv = collect_file(xhp, file, size, pkgname, pkgver, idx, sha256, - TYPE_FILE, remove); + TYPE_FILE, update, preserve, remove); if (rv != 0) goto out; } @@ -503,7 +532,7 @@ collect_files(struct xbps_handle *xhp, xbps_dictionary_t d, size = 0; #endif rv = collect_file(xhp, file, size, pkgname, pkgver, idx, sha256, - TYPE_FILE, remove); + TYPE_FILE, update, preserve, remove); if (rv != 0) goto out; } @@ -513,7 +542,7 @@ collect_files(struct xbps_handle *xhp, xbps_dictionary_t d, filed = xbps_array_get(a, i); xbps_dictionary_get_cstring_nocopy(filed, "file", &file); rv = collect_file(xhp, file, 0, pkgname, pkgver, idx, NULL, - TYPE_LINK, remove); + TYPE_LINK, update, preserve, remove); if (rv != 0) goto out; } @@ -523,7 +552,7 @@ collect_files(struct xbps_handle *xhp, xbps_dictionary_t d, filed = xbps_array_get(a, i); xbps_dictionary_get_cstring_nocopy(filed, "file", &file); rv = collect_file(xhp, file, 0, pkgname, pkgver, idx, NULL, - TYPE_DIR, remove); + TYPE_DIR, update, preserve, remove); if (rv != 0) goto out; } @@ -535,7 +564,7 @@ out: static int collect_binpkg_files(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod, - unsigned int idx) + unsigned int idx, bool update) { xbps_dictionary_t filesd; struct archive *ar = NULL; @@ -614,7 +643,8 @@ collect_binpkg_files(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod, rv = EINVAL; goto out; } - rv = collect_files(xhp, filesd, pkgname, pkgver, idx, false); + rv = collect_files(xhp, filesd, pkgname, pkgver, idx, + update, false, false); goto out; } archive_read_data_skip(ar); @@ -653,7 +683,7 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter) return EINVAL; while ((obj = xbps_object_iterator_next(iter)) != NULL) { - + bool update = false; /* * `idx` is used as package install index, to chose which * choose the first package which owns or used to own the @@ -674,12 +704,12 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter) pkgname = xbps_pkg_name(pkgver); assert(pkgname); + update = strcmp(trans, "update") == 0; - if ((strcmp(trans, "install") == 0) || - (strcmp(trans, "update") == 0)) { + if (update || (strcmp(trans, "install") == 0)) { xbps_set_cb_state(xhp, XBPS_STATE_FILES, 0, pkgver, "%s: collecting files...", pkgver); - rv = collect_binpkg_files(xhp, obj, idx); + rv = collect_binpkg_files(xhp, obj, idx, update); if (rv != 0) goto out; } @@ -711,7 +741,8 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter) assert(oldpkgver); xbps_set_cb_state(xhp, XBPS_STATE_FILES, 0, oldpkgver, "%s: collecting files...", oldpkgver); - rv = collect_files(xhp, filesd, pkgname, pkgver, idx, preserve, true); + rv = collect_files(xhp, filesd, pkgname, pkgver, idx, + update, preserve, true); if (rv != 0) goto out; }