unlink_file: strip trailing slashes

If the user replaces a directory with a symlink, libalpm would get
confused because the trailing slash causes system calls to resolve the
symlink.  This leads to errors and a misleading message during upgrades.
Even though libalpm does not support this, it should not be giving
misleading errors.

Also adds an overflow check.

Fixes FS#51377

Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
This commit is contained in:
Andrew Gregory 2017-04-09 19:49:17 -04:00
parent f9de3b22ad
commit 16b91f798f
3 changed files with 29 additions and 1 deletions

View file

@ -440,8 +440,19 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *oldpkg,
{
struct stat buf;
char file[PATH_MAX];
int file_len;
snprintf(file, PATH_MAX, "%s%s", handle->root, fileobj->name);
file_len = snprintf(file, PATH_MAX, "%s%s", handle->root, fileobj->name);
if(file_len <= 0 || file_len >= PATH_MAX) {
/* 0 is a valid value from snprintf, but should be impossible here */
_alpm_log(handle, ALPM_LOG_DEBUG, "path too long to unlink %s%s\n",
handle->root, fileobj->name);
return -1;
} else if(file[file_len-1] == '/') {
/* trailing slashes cause errors and confusing messages if the user has
* replaced a directory with a symlink */
file[--file_len] = '\0';
}
if(llstat(file, &buf)) {
_alpm_log(handle, ALPM_LOG_DEBUG, "file %s does not exist\n", file);

View file

@ -113,6 +113,7 @@ TESTS += test/pacman/tests/querycheck002.py
TESTS += test/pacman/tests/querycheck_fast_file_type.py
TESTS += test/pacman/tests/reason001.py
TESTS += test/pacman/tests/remove-assumeinstalled.py
TESTS += test/pacman/tests/remove-directory-replaced-with-symlink.py
TESTS += test/pacman/tests/remove-optdepend-of-installed-package.py
TESTS += test/pacman/tests/remove-recursive-cycle.py
TESTS += test/pacman/tests/remove001.py

View file

@ -0,0 +1,16 @@
self.description = "remove a package with a directory that has been replaced with a symlink"
self.filesystem = [ "var/", "srv -> var/" ]
lpkg = pmpkg("pkg1")
lpkg.files = ["srv/"]
self.addpkg2db("local", lpkg)
self.args = "-R %s" % (lpkg.name)
self.addrule("PACMAN_RETCODE=0")
self.addrule("DIR_EXIST=var/")
self.addrule("!LINK_EXIST=srv")
self.addrule("!FILE_EXIST=srv")
self.addrule("!DIR_EXIST=srv")
self.addrule("!PACMAN_OUTPUT=cannot remove")