diff options
author | Allan McRae <allan@archlinux.org> | 2012-07-18 12:25:37 +1000 |
---|---|---|
committer | Allan McRae <allan@archlinux.org> | 2012-12-14 12:35:34 +1000 |
commit | c1abfeae1ec39a196262622662850b7d277a4734 (patch) | |
tree | 2fc58a7cc94d5731117e3a454594bb63b6f4ca76 /lib | |
parent | 6860e2f7032aed392f2526a7fb72cbf08dd3c25f (diff) |
Detect inter-package conflicts between files and directories
Detect a conflict between a file/symlink in one package and a directory
in another when both are being installed at once.
A side effect is the creation of conflicts between a directory symlink
and a real directory (e.g lib -> usr/lib in pkg1 and /lib in pkg2).
Given we can not guarantee pkg1 is installed before pkg2, this is a
genuine conflict.
Signed-off-by: Allan McRae <allan@archlinux.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libalpm/filelist.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/lib/libalpm/filelist.c b/lib/libalpm/filelist.c index f6c0ed45..1928056d 100644 --- a/lib/libalpm/filelist.c +++ b/lib/libalpm/filelist.c @@ -82,27 +82,52 @@ alpm_list_t *_alpm_filelist_intersection(alpm_filelist_t *filesA, size_t ctrA = 0, ctrB = 0; while(ctrA < filesA->count && ctrB < filesB->count) { + int cmp, isdirA, isdirB; + char *strA, *strB; + alpm_file_t *fileA = filesA->files + ctrA; alpm_file_t *fileB = filesB->files + ctrB; - const char *strA = fileA->name; - const char *strB = fileB->name; - /* skip directories, we don't care about them */ + + isdirA = 0; + strA = fileA->name; if(strA[strlen(strA)-1] == '/') { + isdirA = 1; + strA = strndup(fileA->name, strlen(strA)-1); + } + + isdirB = 0; + strB = fileB->name; + if(strB[strlen(strB)-1] == '/') { + isdirB = 1; + strB = strndup(fileB->name, strlen(strB)-1); + } + + cmp = strcmp(strA, strB); + if(cmp < 0) { ctrA++; - } else if(strB[strlen(strB)-1] == '/') { + } else if(cmp > 0) { ctrB++; } else { - int cmp = strcmp(strA, strB); - if(cmp < 0) { - ctrA++; - } else if(cmp > 0) { - ctrB++; - } else { - /* item in both, qualifies as an intersect */ + /* TODO: this creates conflicts between a symlink to a directory in + * one package and a real directory in the other. For example, + * lib -> /usr/lib in pkg1 and /lib in pkg2. This would be allowed + * when installing one package at a time _provided_ pkg1 is installed + * first. This will need adjusted if the order of package install can + * be guaranteed to install the symlink first */ + + /* when not directories, item in both qualifies as an intersect */ + if(! (isdirA && isdirB)) { ret = alpm_list_add(ret, fileA); - ctrA++; - ctrB++; } + ctrA++; + ctrB++; + } + + if(isdirA) { + free(strA); + } + if(isdirB) { + free(strB); } } |