mirror of
https://github.com/archlinuxarm/PKGBUILDs.git
synced 2024-11-18 22:54:00 +00:00
151 lines
5.1 KiB
Diff
151 lines
5.1 KiB
Diff
From 717fdb8ee0fd23cf72fc7d2832317f513caefa2c Mon Sep 17 00:00:00 2001
|
|
From: Allan McRae <allan@archlinux.org>
|
|
Date: Sun, 8 Jul 2012 21:36:36 +1000
|
|
Subject: [PATCH 1/4] Add conflict for replacing owned empty directory
|
|
|
|
When two packages own an empty directory, pacman finds no conflict when
|
|
one of those packages wants to replace the directory with a file or a
|
|
symlink. When it comes to actually extracting the new file/symlink,
|
|
pacman sees the directory is still there (we do not remove empty
|
|
directories if they are owned by a package) and refuses to extract.
|
|
|
|
Detect this potential conflict early and bail. Note that it is a
|
|
_potential_ conflict and not a guaranteed one as the other package owning
|
|
the directory could be updated or removed first which would remove
|
|
the conflict. However, pacman currently can not sort package installation
|
|
order to ensure this, so this conflict requires manual upgrade ordering.
|
|
|
|
Signed-off-by: Allan McRae <allan@archlinux.org>
|
|
Signed-off-by: Dan McGee <dan@archlinux.org>
|
|
---
|
|
lib/libalpm/conflict.c | 32 ++++++++++++++++++++++++++------
|
|
test/pacman/tests/fileconflict009.py | 20 ++++++++++++++++++++
|
|
test/pacman/tests/fileconflict010.py | 20 ++++++++++++++++++++
|
|
3 files changed, 66 insertions(+), 6 deletions(-)
|
|
create mode 100644 test/pacman/tests/fileconflict009.py
|
|
create mode 100644 test/pacman/tests/fileconflict010.py
|
|
|
|
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
|
|
index 32f6f30..efa1a87 100644
|
|
--- a/lib/libalpm/conflict.c
|
|
+++ b/lib/libalpm/conflict.c
|
|
@@ -328,15 +328,35 @@ const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist,
|
|
return NULL;
|
|
}
|
|
|
|
-static int dir_belongsto_pkg(const char *root, const char *dirpath,
|
|
+static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
|
|
alpm_pkg_t *pkg)
|
|
{
|
|
+ alpm_list_t *i;
|
|
struct stat sbuf;
|
|
char path[PATH_MAX];
|
|
char abspath[PATH_MAX];
|
|
- struct dirent *ent = NULL;
|
|
DIR *dir;
|
|
+ struct dirent *ent = NULL;
|
|
+ const char *root = handle->root;
|
|
+
|
|
+ /* TODO: this is an overly strict check but currently pacman will not
|
|
+ * overwrite a directory with a file (case 10/11 in add.c). Adjusting that
|
|
+ * is not simple as even if the directory is being unowned by a conflicting
|
|
+ * package, pacman does not sort this to ensure all required directory
|
|
+ * "removals" happen before installation of file/symlink */
|
|
+
|
|
+ /* check that no other _installed_ package owns the directory */
|
|
+ for(i = _alpm_db_get_pkgcache(handle->db_local); i; i = i->next) {
|
|
+ if(pkg == i->data) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if(_alpm_filelist_contains(alpm_pkg_get_files(i->data), dirpath)) {
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
|
|
+ /* check all files in directory are owned by the package */
|
|
snprintf(abspath, PATH_MAX, "%s%s", root, dirpath);
|
|
dir = opendir(abspath);
|
|
if(dir == NULL) {
|
|
@@ -349,13 +369,13 @@ static int dir_belongsto_pkg(const char *root, const char *dirpath,
|
|
if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
|
|
continue;
|
|
}
|
|
- snprintf(path, PATH_MAX, "%s/%s", dirpath, name);
|
|
+ snprintf(path, PATH_MAX, "%s%s", dirpath, name);
|
|
snprintf(abspath, PATH_MAX, "%s%s", root, path);
|
|
if(stat(abspath, &sbuf) != 0) {
|
|
continue;
|
|
}
|
|
if(S_ISDIR(sbuf.st_mode)) {
|
|
- if(dir_belongsto_pkg(root, path, pkg)) {
|
|
+ if(dir_belongsto_pkg(handle, path, pkg)) {
|
|
continue;
|
|
} else {
|
|
closedir(dir);
|
|
@@ -529,9 +549,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
|
|
sprintf(dir, "%s/", filestr);
|
|
if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), dir)) {
|
|
_alpm_log(handle, ALPM_LOG_DEBUG,
|
|
- "check if all files in %s belongs to %s\n",
|
|
+ "check if all files in %s belong to %s\n",
|
|
dir, dbpkg->name);
|
|
- resolved_conflict = dir_belongsto_pkg(handle->root, filestr, dbpkg);
|
|
+ resolved_conflict = dir_belongsto_pkg(handle, dir, dbpkg);
|
|
}
|
|
free(dir);
|
|
}
|
|
diff --git a/test/pacman/tests/fileconflict009.py b/test/pacman/tests/fileconflict009.py
|
|
new file mode 100644
|
|
index 0000000..904af4a
|
|
--- /dev/null
|
|
+++ b/test/pacman/tests/fileconflict009.py
|
|
@@ -0,0 +1,20 @@
|
|
+self.description = "dir->symlink change during package upgrade (directory conflict)"
|
|
+
|
|
+lp1 = pmpkg("pkg1")
|
|
+lp1.files = ["dir/"]
|
|
+self.addpkg2db("local", lp1)
|
|
+
|
|
+lp2 = pmpkg("pkg2")
|
|
+lp2.files = ["dir/"]
|
|
+self.addpkg2db("local", lp2)
|
|
+
|
|
+p = pmpkg("pkg1", "1.0-2")
|
|
+p.files = ["dir -> /usr/dir"]
|
|
+self.addpkg2db("sync", p)
|
|
+
|
|
+self.args = "-S pkg1"
|
|
+
|
|
+self.addrule("PACMAN_RETCODE=1")
|
|
+self.addrule("PKG_VERSION=pkg1|1.0-1")
|
|
+self.addrule("PKG_VERSION=pkg2|1.0-1")
|
|
+self.addrule("DIR_EXIST=dir/")
|
|
diff --git a/test/pacman/tests/fileconflict010.py b/test/pacman/tests/fileconflict010.py
|
|
new file mode 100644
|
|
index 0000000..0a3ce83
|
|
--- /dev/null
|
|
+++ b/test/pacman/tests/fileconflict010.py
|
|
@@ -0,0 +1,20 @@
|
|
+self.description = "dir->file change during package upgrade (directory conflict)"
|
|
+
|
|
+lp1 = pmpkg("pkg1")
|
|
+lp1.files = ["dir/"]
|
|
+self.addpkg2db("local", lp1)
|
|
+
|
|
+lp2 = pmpkg("pkg2")
|
|
+lp2.files = ["dir/"]
|
|
+self.addpkg2db("local", lp2)
|
|
+
|
|
+p = pmpkg("pkg1", "1.0-2")
|
|
+p.files = ["dir"]
|
|
+self.addpkg2db("sync", p)
|
|
+
|
|
+self.args = "-S pkg1"
|
|
+
|
|
+self.addrule("PACMAN_RETCODE=1")
|
|
+self.addrule("PKG_VERSION=pkg1|1.0-1")
|
|
+self.addrule("PKG_VERSION=pkg2|1.0-1")
|
|
+self.addrule("DIR_EXIST=dir/")
|
|
--
|
|
1.7.11.1
|