libxbps: properly detect obsolete files with files being between pkgs.

120 test cases now successfully pass, and all known issues about
pkg updates that move files between them should be gone (hopefully).
This commit is contained in:
Juan RP 2015-02-26 19:37:46 +01:00
parent 8de52caa2f
commit b6b446d32e
4 changed files with 37 additions and 13 deletions

4
NEWS
View File

@ -1,5 +1,9 @@
xbps-0.44 (???): xbps-0.44 (???):
* libxbps: properly detect when a file has been moved between packages:
if the mtime stored in the pkg metadata does not match the mtime
of the same file stored on disk, don't detect this as an obsolete file.
* xbps-pkgdb(8): this now exits with an error if any test has failed. * xbps-pkgdb(8): this now exits with an error if any test has failed.
* libxbps: while unpacking pkg files that were not modified (sha256 hash matched), * libxbps: while unpacking pkg files that were not modified (sha256 hash matched),

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2009-2014 Juan Romero Pardines. * Copyright (c) 2009-2015 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -76,8 +76,6 @@ xbps_find_pkg_obsoletes(struct xbps_handle *xhp,
xbps_dictionary_t newd) xbps_dictionary_t newd)
{ {
xbps_array_t instfiles, newfiles, obsoletes; xbps_array_t instfiles, newfiles, obsoletes;
xbps_object_t obj, obj2;
xbps_string_t oldstr, newstr;
/* These are symlinks in Void and must not be removed */ /* These are symlinks in Void and must not be removed */
const char *basesymlinks[] = { const char *basesymlinks[] = {
"./bin", "./bin",
@ -89,10 +87,7 @@ xbps_find_pkg_obsoletes(struct xbps_handle *xhp,
"./usr/lib64", "./usr/lib64",
"./var/run", "./var/run",
}; };
const char *oldhash;
char file[PATH_MAX];
int rv = 0; int rv = 0;
bool found;
assert(xbps_object_type(instd) == XBPS_TYPE_DICTIONARY); assert(xbps_object_type(instd) == XBPS_TYPE_DICTIONARY);
assert(xbps_object_type(newd) == XBPS_TYPE_DICTIONARY); assert(xbps_object_type(newd) == XBPS_TYPE_DICTIONARY);
@ -112,7 +107,14 @@ xbps_find_pkg_obsoletes(struct xbps_handle *xhp,
* Iterate over files list from installed package. * Iterate over files list from installed package.
*/ */
for (unsigned int i = 0; i < xbps_array_count(instfiles); i++) { for (unsigned int i = 0; i < xbps_array_count(instfiles); i++) {
found = false; xbps_object_t obj, obj2;
xbps_string_t oldstr, newstr;
struct stat st;
uint64_t mtime = 0;
const char *oldhash;
char file[PATH_MAX];
bool found = false;
obj = xbps_array_get(instfiles, i); obj = xbps_array_get(instfiles, i);
if (xbps_object_type(obj) != XBPS_TYPE_DICTIONARY) { if (xbps_object_type(obj) != XBPS_TYPE_DICTIONARY) {
/* ignore unexistent files */ /* ignore unexistent files */
@ -124,13 +126,11 @@ xbps_find_pkg_obsoletes(struct xbps_handle *xhp,
snprintf(file, sizeof(file), ".%s", xbps_string_cstring_nocopy(oldstr)); snprintf(file, sizeof(file), ".%s", xbps_string_cstring_nocopy(oldstr));
oldhash = NULL; if (xbps_dictionary_get_cstring_nocopy(obj, "sha256", &oldhash)) {
xbps_dictionary_get_cstring_nocopy(obj, "sha256", &oldhash);
if (oldhash) {
rv = xbps_file_hash_check(file, oldhash); rv = xbps_file_hash_check(file, oldhash);
if (rv == ENOENT || rv == ERANGE) { if (rv == ENOENT || rv == ERANGE) {
/* /*
* Skip unexistent and files that do not Skip unexistent and files that do not
* match the hash. * match the hash.
*/ */
continue; continue;
@ -157,7 +157,6 @@ xbps_find_pkg_obsoletes(struct xbps_handle *xhp,
/* /*
* Make sure to not remove any symlink of root directory. * Make sure to not remove any symlink of root directory.
*/ */
found = false;
for (uint8_t x = 0; x < __arraycount(basesymlinks); x++) { for (uint8_t x = 0; x < __arraycount(basesymlinks); x++) {
if (strcmp(file, basesymlinks[x]) == 0) { if (strcmp(file, basesymlinks[x]) == 0) {
found = true; found = true;
@ -169,6 +168,22 @@ xbps_find_pkg_obsoletes(struct xbps_handle *xhp,
if (found) { if (found) {
continue; continue;
} }
/*
* Finally check if file mtime on disk matched what
* the installed pkg has stored.
*/
if (xbps_dictionary_get_uint64(obj, "mtime", &mtime)) {
if (lstat(file, &st) == -1) {
xbps_dbg_printf(xhp, "[obsoletes] lstat failed "
"for %s: %s\n", file, strerror(errno));
continue;
}
if (mtime != (uint64_t)st.st_mtime)
continue;
xbps_dbg_printf(xhp,
"[obsoletes] %s: matched mtime, adding obsolete.\n", file);
}
/* /*
* Obsolete found, add onto the array. * Obsolete found, add onto the array.
*/ */

View File

@ -315,7 +315,7 @@ update_file_timestamps_body() {
atf_check_equal "$expected" "$result" atf_check_equal "$expected" "$result"
sleep 2 sleep 1
cd repo cd repo
touch -f pkg_A/usr/include/gsm/gsm.h touch -f pkg_A/usr/include/gsm/gsm.h
xbps-create -A noarch -n foo-1.1_1 -s "foo pkg" ../pkg_A xbps-create -A noarch -n foo-1.1_1 -s "foo pkg" ../pkg_A
@ -386,6 +386,7 @@ update_move_file_body() {
xbps-rindex -d -a repo/*.xbps xbps-rindex -d -a repo/*.xbps
atf_check_equal $? 0 atf_check_equal $? 0
xbps-install -r root --repository=repo -yvd A B xbps-install -r root --repository=repo -yvd A B
sleep 1
cd repo cd repo
rm ../pkg_B/usr/bin/sg rm ../pkg_B/usr/bin/sg
rm ../pkg_A/usr/bin/newgrp rm ../pkg_A/usr/bin/newgrp

View File

@ -212,7 +212,11 @@ files_move_to_dependency2_body() {
xbps-install -r root --repository=$PWD -yvd libressl xbps-install -r root --repository=$PWD -yvd libressl
atf_check_equal $? 0 atf_check_equal $? 0
sleep 1
rm -f ../pkg_libressl/usr/lib/libcrypto.* rm -f ../pkg_libressl/usr/lib/libcrypto.*
touch -f ../pkg_libcrypto/usr/lib/libcrypto.so.30
xbps-create -A noarch -n libcrypto-1.0_2 -s "libcrypto pkg" ../pkg_libcrypto
atf_check_equal $? 0
xbps-create -A noarch -n libressl-1.1_1 -s "libressl pkg" --dependencies "libcrypto>=1.0" ../pkg_libressl xbps-create -A noarch -n libressl-1.1_1 -s "libressl pkg" --dependencies "libcrypto>=1.0" ../pkg_libressl
atf_check_equal $? 0 atf_check_equal $? 0
xbps-rindex -d -a $PWD/*.xbps xbps-rindex -d -a $PWD/*.xbps