summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/conflict.c
diff options
context:
space:
mode:
authorXavier Chantry <shiningxc@gmail.com>2009-07-17 15:48:57 +0200
committerDan McGee <dan@archlinux.org>2009-07-20 17:13:25 +0200
commitbfd6817112b34b552e9139bdc582d048bcba38b9 (patch)
tree1c33649fec71af2d5a16618bd9627689c0a54285 /lib/libalpm/conflict.c
parenta3ecbec6b584b3595c041850e4c8bf242f7ce74a (diff)
downloadpacman-bfd6817112b34b552e9139bdc582d048bcba38b9.tar.gz
pacman-bfd6817112b34b552e9139bdc582d048bcba38b9.tar.xz
Fix fileconflict004
When one package wants to replace a directory by a file, we check that all files in that directory were owned by that package. Additionally pacman can be more verbose when the extraction of the symlink (or file) fails. The patch to add.c looks more complex than it is, I just moved and reindented code to handle cases 10 and 11 together. Signed-off-by: Xavier Chantry <shiningxc@gmail.com> Signed-off-by: Dan McGee <dan@archlinux.org>
Diffstat (limited to 'lib/libalpm/conflict.c')
-rw-r--r--lib/libalpm/conflict.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index db1656fa..c4c57cb0 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
+#include <dirent.h>
/* libalpm */
#include "conflict.h"
@@ -348,6 +349,50 @@ void _alpm_fileconflict_free(pmfileconflict_t *conflict)
FREE(conflict);
}
+static int dir_belongsto_pkg(char *dirpath, pmpkg_t *pkg)
+{
+ struct dirent *ent = NULL;
+ struct stat sbuf;
+ char path[PATH_MAX];
+ char abspath[PATH_MAX];
+ DIR *dir;
+
+ snprintf(abspath, PATH_MAX, "%s%s", handle->root, dirpath);
+ dir = opendir(abspath);
+ if(dir == NULL) {
+ return(1);
+ }
+ while((ent = readdir(dir)) != NULL) {
+ const char *name = ent->d_name;
+
+ if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
+ continue;
+ }
+ snprintf(path, PATH_MAX, "%s/%s", dirpath, name);
+ snprintf(abspath, PATH_MAX, "%s%s", handle->root, path);
+ if(stat(abspath, &sbuf) != 0) {
+ continue;
+ }
+ if(S_ISDIR(sbuf.st_mode)) {
+ if(dir_belongsto_pkg(path, pkg)) {
+ continue;
+ } else {
+ closedir(dir);
+ return(0);
+ }
+ } else {
+ if(alpm_list_find_str(alpm_pkg_get_files(pkg),path)) {
+ continue;
+ } else {
+ closedir(dir);
+ return(0);
+ }
+ }
+ }
+ closedir(dir);
+ return(1);
+}
+
/* Find file conflicts that may occur during the transaction with two checks:
* 1: check every target against every target
* 2: check every target against the filesystem */
@@ -474,6 +519,18 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans,
}
}
+ /* check if all files of the dir belong to the installed pkg */
+ if(!resolved_conflict && S_ISDIR(lsbuf.st_mode) && dbpkg) {
+ char *dir = malloc(strlen(filestr) + 2);
+ sprintf(dir, "%s/", filestr);
+ if(alpm_list_find_str(alpm_pkg_get_files(dbpkg),dir)) {
+ _alpm_log(PM_LOG_DEBUG, "check if all files in %s belongs to %s\n",
+ dir, dbpkg->name);
+ resolved_conflict = dir_belongsto_pkg(filestr, dbpkg);
+ }
+ free(dir);
+ }
+
if(!resolved_conflict) {
_alpm_log(PM_LOG_DEBUG, "file found in conflict: %s\n", path);
conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_FILESYSTEM,