Make sure that modified symlinks are preserved.
When removing a package, symlinks owned by this package that have been modified should be preserved, unless the force flag is set via xbps-remove(8).
This commit is contained in:
parent
b81dedb770
commit
5fe3594cb5
@ -92,6 +92,43 @@ check_remove_pkg_files(struct xbps_handle *xhp,
|
|||||||
return fail;
|
return fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
symlink_target(struct xbps_handle *xhp, const char *path)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
char *lnk, *res;
|
||||||
|
ssize_t r;
|
||||||
|
|
||||||
|
if (lstat(path, &sb) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
lnk = malloc(sb.st_size + 1);
|
||||||
|
assert(lnk);
|
||||||
|
|
||||||
|
r = readlink(path, lnk, sb.st_size + 1);
|
||||||
|
if (r < 0 || r > sb.st_size) {
|
||||||
|
free(lnk);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
lnk[sb.st_size] = '\0';
|
||||||
|
if ((strncmp(lnk, "../", 3) == 0) || strchr(lnk, '/') == NULL) {
|
||||||
|
char *p, *dname;
|
||||||
|
|
||||||
|
/* relative */
|
||||||
|
p = strdup(path);
|
||||||
|
assert(p);
|
||||||
|
dname = dirname(p);
|
||||||
|
assert(dname);
|
||||||
|
dname += strlen(xhp->rootdir) + 1;
|
||||||
|
res = xbps_xasprintf("%s/%s", dname, lnk);
|
||||||
|
free(lnk);
|
||||||
|
} else {
|
||||||
|
/* absolute */
|
||||||
|
res = lnk;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
remove_pkg_files(struct xbps_handle *xhp,
|
remove_pkg_files(struct xbps_handle *xhp,
|
||||||
xbps_dictionary_t dict,
|
xbps_dictionary_t dict,
|
||||||
@ -101,7 +138,7 @@ remove_pkg_files(struct xbps_handle *xhp,
|
|||||||
xbps_array_t array;
|
xbps_array_t array;
|
||||||
xbps_object_iterator_t iter;
|
xbps_object_iterator_t iter;
|
||||||
xbps_object_t obj;
|
xbps_object_t obj;
|
||||||
const char *file, *sha256, *curobj = NULL;
|
const char *curobj = NULL;
|
||||||
/* 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",
|
||||||
@ -113,9 +150,7 @@ remove_pkg_files(struct xbps_handle *xhp,
|
|||||||
"/usr/lib64",
|
"/usr/lib64",
|
||||||
"/var/run",
|
"/var/run",
|
||||||
};
|
};
|
||||||
char path[PATH_MAX];
|
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
bool found;
|
|
||||||
|
|
||||||
assert(xbps_object_type(dict) == XBPS_TYPE_DICTIONARY);
|
assert(xbps_object_type(dict) == XBPS_TYPE_DICTIONARY);
|
||||||
assert(key != NULL);
|
assert(key != NULL);
|
||||||
@ -140,6 +175,10 @@ remove_pkg_files(struct xbps_handle *xhp,
|
|||||||
xbps_object_iterator_reset(iter);
|
xbps_object_iterator_reset(iter);
|
||||||
|
|
||||||
while ((obj = xbps_object_iterator_next(iter))) {
|
while ((obj = xbps_object_iterator_next(iter))) {
|
||||||
|
const char *file, *sha256;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
bool found;
|
||||||
|
|
||||||
xbps_dictionary_get_cstring_nocopy(obj, "file", &file);
|
xbps_dictionary_get_cstring_nocopy(obj, "file", &file);
|
||||||
snprintf(path, sizeof(path), "%s/%s", xhp->rootdir, file);
|
snprintf(path, sizeof(path), "%s/%s", xhp->rootdir, file);
|
||||||
|
|
||||||
@ -205,6 +244,29 @@ remove_pkg_files(struct xbps_handle *xhp,
|
|||||||
if (found) {
|
if (found) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (strcmp(key, "links") == 0) {
|
||||||
|
const char *target = NULL;
|
||||||
|
char *lnk;
|
||||||
|
|
||||||
|
lnk = symlink_target(xhp, path);
|
||||||
|
if (lnk == NULL) {
|
||||||
|
xbps_dbg_printf(xhp, "[remove] %s "
|
||||||
|
"symlink_target: %s\n", path, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
xbps_dictionary_get_cstring_nocopy(obj, "target", &target);
|
||||||
|
assert(target);
|
||||||
|
if (strcmp(lnk, target)) {
|
||||||
|
xbps_dbg_printf(xhp, "[remove] %s symlink "
|
||||||
|
"modified (stored %s current %s)\n", path,
|
||||||
|
target, lnk);
|
||||||
|
if ((xhp->flags & XBPS_FLAG_FORCE_REMOVE_FILES) == 0) {
|
||||||
|
free(lnk);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(lnk);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Remove the object if possible.
|
* Remove the object if possible.
|
||||||
*/
|
*/
|
||||||
|
@ -105,6 +105,69 @@ remove_symlinks_from_root_body() {
|
|||||||
atf_check_equal $rv 0
|
atf_check_equal $rv 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atf_test_case keep_modified_symlinks
|
||||||
|
|
||||||
|
keep_modified_symlinks_head() {
|
||||||
|
atf_set "descr" "Tests for package removal: keep modified symlinks in rootdir"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_modified_symlinks_body() {
|
||||||
|
mkdir some_repo
|
||||||
|
mkdir -p pkg_A/bin
|
||||||
|
ln -sf /bin/bash pkg_A/bin/ash
|
||||||
|
ln -sf /bin/bash pkg_A/bin/sh
|
||||||
|
|
||||||
|
cd some_repo
|
||||||
|
xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A
|
||||||
|
atf_check_equal $? 0
|
||||||
|
xbps-rindex -a *.xbps
|
||||||
|
atf_check_equal $? 0
|
||||||
|
cd ..
|
||||||
|
xbps-install -r root -C null.conf --repository=$PWD/some_repo -y A
|
||||||
|
atf_check_equal $? 0
|
||||||
|
ln -sf /bin/foo root/bin/sh
|
||||||
|
ln -sf foo root/bin/ash
|
||||||
|
|
||||||
|
xbps-remove -r root -yvd A
|
||||||
|
atf_check_equal $? 0
|
||||||
|
rv=1
|
||||||
|
if [ -h root/bin/sh -a -h root/bin/ash ]; then
|
||||||
|
rv=0
|
||||||
|
fi
|
||||||
|
atf_check_equal $rv 0
|
||||||
|
}
|
||||||
|
|
||||||
|
atf_test_case remove_symlinks_modified
|
||||||
|
|
||||||
|
remove_symlinks_modified_head() {
|
||||||
|
atf_set "descr" "Tests for package removal: force remove modified symlinks in rootdir"
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_symlinks_modified_body() {
|
||||||
|
mkdir some_repo
|
||||||
|
mkdir -p pkg_A/bin
|
||||||
|
ln -sf /bin/bash pkg_A/bin/ash
|
||||||
|
ln -sf /bin/bash pkg_A/bin/sh
|
||||||
|
|
||||||
|
cd some_repo
|
||||||
|
xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A
|
||||||
|
atf_check_equal $? 0
|
||||||
|
xbps-rindex -a *.xbps
|
||||||
|
atf_check_equal $? 0
|
||||||
|
cd ..
|
||||||
|
xbps-install -r root -C null.conf --repository=$PWD/some_repo -y A
|
||||||
|
atf_check_equal $? 0
|
||||||
|
ln -sf /bin/foo root/bin/sh
|
||||||
|
|
||||||
|
xbps-remove -r root -yvfd A
|
||||||
|
atf_check_equal $? 0
|
||||||
|
rv=0
|
||||||
|
if [ -h root/bin/sh -o -h root/bin/ash ]; then
|
||||||
|
rv=1
|
||||||
|
fi
|
||||||
|
atf_check_equal $rv 0
|
||||||
|
}
|
||||||
|
|
||||||
atf_test_case remove_readonly_files
|
atf_test_case remove_readonly_files
|
||||||
|
|
||||||
remove_readonly_files_head() {
|
remove_readonly_files_head() {
|
||||||
@ -160,8 +223,10 @@ remove_dups_body() {
|
|||||||
|
|
||||||
atf_init_test_cases() {
|
atf_init_test_cases() {
|
||||||
atf_add_test_case keep_base_symlinks
|
atf_add_test_case keep_base_symlinks
|
||||||
|
atf_add_test_case keep_modified_symlinks
|
||||||
atf_add_test_case remove_readonly_files
|
atf_add_test_case remove_readonly_files
|
||||||
atf_add_test_case remove_symlinks
|
atf_add_test_case remove_symlinks
|
||||||
atf_add_test_case remove_symlinks_from_root
|
atf_add_test_case remove_symlinks_from_root
|
||||||
|
atf_add_test_case remove_symlinks_modified
|
||||||
atf_add_test_case remove_dups
|
atf_add_test_case remove_dups
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user