[pacman-dev] [PATCH] lib/conflict: avoid conflict with unchanged effective path

Dave Reisner dreisner at archlinux.org
Sat Jul 14 23:21:50 EDT 2012


This applies to a case such as when /lib is a symlink to /usr/lib. If a
package is installed which contains /lib/libfoo.so, pacman will complain
if this package is then "fixed" to contain /usr/lib/libfoo.so. Since
these have the same effective path and it exists within the same
package, ignore the conflict.

Fixes FS#30681.

Signed-off-by: Dave Reisner <dreisner at archlinux.org>
---
Written against maint.

 lib/libalpm/conflict.c               | 34 ++++++++++++++++++++++++++++++++++
 test/pacman/tests/fileconflict013.py | 20 ++++++++++++++++++++
 2 files changed, 54 insertions(+)
 create mode 100644 test/pacman/tests/fileconflict013.py

diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index d6e5d8c..64dd5b0 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -314,6 +314,28 @@ void _alpm_fileconflict_free(alpm_fileconflict_t *conflict)
 	FREE(conflict);
 }
 
+static const alpm_file_t *_alpm_filelist_contains_resolved(alpm_filelist_t *filelist,
+		const char *name, const char *root, size_t rootlen)
+{
+	size_t i;
+	const alpm_file_t *file;
+
+	if(!filelist) {
+		return NULL;
+	}
+
+	for(file = filelist->files, i = 0; i < filelist->count; file++, i++) {
+		char fullpath[PATH_MAX], abspath[PATH_MAX];
+		snprintf(fullpath, sizeof(fullpath), "%s%s", root, file->name);
+		if(realpath(fullpath, abspath)) {
+			if(strcmp(&abspath[rootlen], name) == 0) {
+				return file;
+			}
+		}
+	}
+	return NULL;
+}
+
 const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist,
 		const char *name)
 {
@@ -579,6 +601,18 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
 				free(rpath);
 			}
 
+			/* check if any of the package's own files resolve to the conflict to
+			 * prevent problems with, e.g. /lib/liba.so moving to /usr/lib/liba.so
+			 * when /lib is a symlink to usr/lib */
+			if(!resolved_conflict && dbpkg && !S_ISDIR(lsbuf.st_mode)) {
+				if(_alpm_filelist_contains_resolved(alpm_pkg_get_files(dbpkg),
+							relative_path, handle->root, rootlen)) {
+					_alpm_log(handle, ALPM_LOG_DEBUG,
+							"package contained a realpath resolved to a package file\n");
+					resolved_conflict = 1;
+				}
+			}
+
 			/* is the file unowned and in the backup list of the new package? */
 			if(!resolved_conflict && _alpm_needbackup(filestr, p1)) {
 				alpm_list_t *local_pkgs = _alpm_db_get_pkgcache(handle->db_local);
diff --git a/test/pacman/tests/fileconflict013.py b/test/pacman/tests/fileconflict013.py
new file mode 100644
index 0000000..a83923c
--- /dev/null
+++ b/test/pacman/tests/fileconflict013.py
@@ -0,0 +1,20 @@
+self.description = "file->file path change with same effective path (/lib as symlink)"
+
+lp1 = pmpkg("filesystem", "1.0-1")
+lp1.files = ["usr/",
+             "usr/lib/",
+             "lib -> usr/lib/"]
+self.addpkg2db("local", lp1)
+
+lp2 = pmpkg("pkg1", "1.0-1")
+lp2.files = ["lib/libfoo.so"]
+self.addpkg2db("local", lp2)
+
+sp1 = pmpkg("pkg1", "1.0-2")
+sp1.files = ["usr/lib/libfoo.so"]
+self.addpkg2db("sync", sp1)
+
+self.args = "-Su"
+
+self.addrule("PACMAN_RETCODE=0")
+self.addrule("PKG_VERSION=pkg1|1.0-2")
-- 
1.7.11.2



More information about the pacman-dev mailing list