* 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 <[email protected]>
---

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


Reply via email to