[pacman-dev] Conflict when replacing a folder with subfolders by a file in a package update
Hi, Pacman exits with a conflict error if the package updated is replacing a folder with subfolders inside by a single file with the same name. This may be a bug as I don't know any cases where this cloud make sense. But I may be wrong of course. I'll let you decide. Testing was done on fully updated Arch Linux system with the following repositories enabled: kf5, kde-unstable, testing, core, extra, community-testing, community, multilib-testing, multilib. Example PKGBUILDs to reproduce the issue: $ cat PKGBUILD.1 pkgname=testpkg pkgver=1 pkgrel=1 pkgdesc="Test package" arch=('i686' 'x86_64') license=('GPL') package() { cd "${pkgdir}" mkdir -p usr/test/test } $ cat PKGBUILD.2 pkgname=testpkg pkgver=1 pkgrel=2 pkgdesc="Test package" arch=('i686' 'x86_64') license=('GPL') package() { cd "${pkgdir}" mkdir usr touch usr/test } Pacman output: $ sudo pacman -U testpkg-1-2-x86_64.pkg.tar.xz loading packages... resolving dependencies... looking for inter-conflicts... Packages (1): Name Old Version New Version Net Change testpkg 1-1 1-2 0.00 MiB Total Installed Size: 0.00 MiB Net Upgrade Size: 0.00 MiB :: Proceed with installation? [Y/n] (1/1) checking keys in keyring [--------------------------------------] 100% (1/1) checking package integrity [--------------------------------------] 100% (1/1) loading package files [--------------------------------------] 100% (1/1) checking for file conflicts [--------------------------------------] 100% error: failed to commit transaction (conflicting files) testpkg: /usr/test exists in filesystem Errors occurred, no packages were upgraded. Cheers, Tim
On 06/08/13 00:33, Timothée Ravier wrote:
Hi,
Pacman exits with a conflict error if the package updated is replacing a folder with subfolders inside by a single file with the same name.
This may be a bug as I don't know any cases where this cloud make sense. But I may be wrong of course. I'll let you decide.
Testing was done on fully updated Arch Linux system with the following repositories enabled: kf5, kde-unstable, testing, core, extra, community-testing, community, multilib-testing, multilib.
Example PKGBUILDs to reproduce the issue:
<snip> Confirmed using pacman-git. We need a bug report and a pactest for this (and even a fix!) Any volunteers? Allan
On 08/07/13 at 10:54pm, Allan McRae wrote:
On 06/08/13 00:33, Timothée Ravier wrote:
Hi,
Pacman exits with a conflict error if the package updated is replacing a folder with subfolders inside by a single file with the same name.
This may be a bug as I don't know any cases where this cloud make sense. But I may be wrong of course. I'll let you decide.
Testing was done on fully updated Arch Linux system with the following repositories enabled: kf5, kde-unstable, testing, core, extra, community-testing, community, multilib-testing, multilib.
Example PKGBUILDs to reproduce the issue:
<snip>
Confirmed using pacman-git. We need a bug report and a pactest for this (and even a fix!) Any volunteers?
Allan
It's an easy enough fix. I forgot to add a slash to directories in dir_belongsto_pkgs. I can fix it this weekend if nobody else gets to it before that. apg
* append "/" to directories before searching package file lists * use lstat over stat so symlinks aren't resolved * fix the inverted check for stat's return value Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com> --- The included fileconflict032 will actually currently _pass_ on both master and maint due to the other bugs masking the problem with using stat instead of lstat. lib/libalpm/conflict.c | 16 ++++++++++++---- test/pacman/tests/fileconflict031.py | 16 ++++++++++++++++ test/pacman/tests/fileconflict032.py | 17 +++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 test/pacman/tests/fileconflict031.py create mode 100644 test/pacman/tests/fileconflict032.py diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index a00efe5..54ed25e 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -323,7 +323,7 @@ static int dir_belongsto_pkgs(alpm_handle_t *handle, const char *dirpath, while((ent = readdir(dir)) != NULL) { const char *name = ent->d_name; - int owned = 0; + int owned = 0, is_dir = 0; alpm_list_t *i; struct stat sbuf; @@ -331,8 +331,16 @@ static int dir_belongsto_pkgs(alpm_handle_t *handle, const char *dirpath, continue; } - snprintf(path, PATH_MAX, "%s%s", dirpath, name); - snprintf(full_path, PATH_MAX, "%s%s", handle->root, path); + snprintf(full_path, PATH_MAX, "%s%s%s", handle->root, dirpath, name); + + if(lstat(full_path, &sbuf) != 0) { + _alpm_log(handle, ALPM_LOG_DEBUG, "could not stat %s\n", full_path); + closedir(dir); + return 0; + } + is_dir = S_ISDIR(sbuf.st_mode); + + snprintf(path, PATH_MAX, "%s%s%s", dirpath, name, is_dir ? "/" : ""); for(i = pkgs; i && !owned; i = i->next) { if(alpm_filelist_contains(alpm_pkg_get_files(i->data), path)) { @@ -340,7 +348,7 @@ static int dir_belongsto_pkgs(alpm_handle_t *handle, const char *dirpath, } } - if(owned && stat(full_path, &sbuf) != 0 && S_ISDIR(sbuf.st_mode)) { + if(owned && is_dir) { owned = dir_belongsto_pkgs(handle, path, pkgs); } diff --git a/test/pacman/tests/fileconflict031.py b/test/pacman/tests/fileconflict031.py new file mode 100644 index 0000000..7d38141 --- /dev/null +++ b/test/pacman/tests/fileconflict031.py @@ -0,0 +1,16 @@ +self.description = "Dir->file transition filesystem conflict resolved by removal (with subdirectory)" + +lp1 = pmpkg("foo") +lp1.files = ["foo/bar/"] +self.addpkg2db("local", lp1) + +sp1 = pmpkg("foo", "2-1") +sp1.conflicts = ["foo"] +sp1.files = ["foo"] +self.addpkg2db("sync", sp1) + +self.args = "-S %s" % sp1.name + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=foo|2-1") +self.addrule("FILE_EXIST=foo") diff --git a/test/pacman/tests/fileconflict032.py b/test/pacman/tests/fileconflict032.py new file mode 100644 index 0000000..9a67735 --- /dev/null +++ b/test/pacman/tests/fileconflict032.py @@ -0,0 +1,17 @@ +self.description = "Dir->file transition filesystem conflict resolved by removal (with symlink)" + +self.filesystem = ["baz/quux"] + +lp1 = pmpkg("foo") +lp1.files = ["foo/bar -> ../baz/"] +self.addpkg2db("local", lp1) + +sp1 = pmpkg("foo", "2-1") +sp1.files = ["foo"] +self.addpkg2db("sync", sp1) + +self.args = "-S %s" % sp1.name + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=foo|2-1") +self.addrule("FILE_EXIST=foo") -- 1.8.3.4
participants (3)
-
Allan McRae
-
Andrew Gregory
-
Timothée Ravier