summaryrefslogtreecommitdiff
path: root/lib/libalpm/conflict.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/conflict.c')
-rw-r--r--lib/libalpm/conflict.c128
1 files changed, 27 insertions, 101 deletions
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index 6bfd256f..ccfe990c 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -1,7 +1,7 @@
/*
* conflict.c
*
- * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
+ * Copyright (c) 2006-2012 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
* Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org>
@@ -22,8 +22,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -40,6 +38,7 @@
#include "util.h"
#include "log.h"
#include "deps.h"
+#include "filelist.h"
static alpm_conflict_t *conflict_new(alpm_pkg_t *pkg1, alpm_pkg_t *pkg2,
alpm_depend_t *reason)
@@ -215,67 +214,6 @@ alpm_list_t SYMEXPORT *alpm_checkconflicts(alpm_handle_t *handle,
return _alpm_innerconflicts(handle, pkglist);
}
-static const int DIFFERENCE = 0;
-static const int INTERSECT = 1;
-/* Returns a set operation on the provided two lists of files.
- * Pre-condition: both lists are sorted!
- * When done, free the list but NOT the contained data.
- *
- * Operations:
- * DIFFERENCE - a difference operation is performed. filesA - filesB.
- * INTERSECT - an intersection operation is performed. filesA & filesB.
- */
-static alpm_list_t *filelist_operation(alpm_filelist_t *filesA,
- alpm_filelist_t *filesB, int operation)
-{
- alpm_list_t *ret = NULL;
- size_t ctrA = 0, ctrB = 0;
-
- while(ctrA < filesA->count && ctrB < filesB->count) {
- 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 */
- if(strA[strlen(strA)-1] == '/') {
- ctrA++;
- } else if(strB[strlen(strB)-1] == '/') {
- ctrB++;
- } else {
- int cmp = strcmp(strA, strB);
- if(cmp < 0) {
- if(operation == DIFFERENCE) {
- /* item only in filesA, qualifies as a difference */
- ret = alpm_list_add(ret, fileA);
- }
- ctrA++;
- } else if(cmp > 0) {
- ctrB++;
- } else {
- if(operation == INTERSECT) {
- /* item in both, qualifies as an intersect */
- ret = alpm_list_add(ret, fileA);
- }
- ctrA++;
- ctrB++;
- }
- }
- }
-
- /* if doing a difference, ensure we have completely emptied pA */
- while(operation == DIFFERENCE && ctrA < filesA->count) {
- alpm_file_t *fileA = filesA->files + ctrA;
- const char *strA = fileA->name;
- /* skip directories */
- if(strA[strlen(strA)-1] != '/') {
- ret = alpm_list_add(ret, fileA);
- }
- ctrA++;
- }
-
- return ret;
-}
-
/* Adds alpm_fileconflict_t to a conflicts list. Pass the conflicts list, the
* conflicting file path, and either two packages or one package and NULL.
*/
@@ -314,20 +252,6 @@ void _alpm_fileconflict_free(alpm_fileconflict_t *conflict)
FREE(conflict);
}
-const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist,
- const char *name)
-{
- size_t i;
- const alpm_file_t *file = filelist->files;
- for(i = 0; i < filelist->count; i++) {
- if(strcmp(file->name, name) == 0) {
- return file;
- }
- file++;
- }
- return NULL;
-}
-
static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
alpm_pkg_t *pkg)
{
@@ -340,7 +264,7 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
const char *root = handle->root;
/* check directory is actually in package - used for subdirectory checks */
- if(!_alpm_filelist_contains(alpm_pkg_get_files(pkg), dirpath)) {
+ if(!alpm_filelist_contains(alpm_pkg_get_files(pkg), dirpath)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"directory %s not in package %s\n", dirpath, pkg->name);
return 0;
@@ -358,7 +282,7 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
continue;
}
- if(_alpm_filelist_contains(alpm_pkg_get_files(i->data), dirpath)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(i->data), dirpath)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"file %s also in package %s\n", dirpath,
((alpm_pkg_t*)i->data)->name);
@@ -392,7 +316,7 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
return 0;
}
} else {
- if(_alpm_filelist_contains(alpm_pkg_get_files(pkg), path)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(pkg), path)) {
continue;
} else {
closedir(dir);
@@ -410,16 +334,19 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
* 1: check every target against every target
* 2: check every target against the filesystem */
alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
- alpm_list_t *upgrade, alpm_list_t *remove)
+ alpm_list_t *upgrade, alpm_list_t *rem)
{
alpm_list_t *i, *conflicts = NULL;
size_t numtargs = alpm_list_count(upgrade);
size_t current;
+ size_t rootlen;
if(!upgrade) {
return NULL;
}
+ rootlen = strlen(handle->root);
+
/* TODO this whole function needs a huge change, which hopefully will
* be possible with real transactions. Right now we only do half as much
* here as we do when we actually extract files in add.c with our 12
@@ -440,8 +367,8 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
for(j = i->next; j; j = j->next) {
alpm_list_t *common_files;
alpm_pkg_t *p2 = j->data;
- common_files = filelist_operation(alpm_pkg_get_files(p1),
- alpm_pkg_get_files(p2), INTERSECT);
+ common_files = _alpm_filelist_intersection(alpm_pkg_get_files(p1),
+ alpm_pkg_get_files(p2));
if(common_files) {
alpm_list_t *k;
@@ -473,8 +400,8 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
if(dbpkg) {
alpm_list_t *difference;
/* older ver of package currently installed */
- difference = filelist_operation(alpm_pkg_get_files(p1),
- alpm_pkg_get_files(dbpkg), DIFFERENCE);
+ difference = _alpm_filelist_difference(alpm_pkg_get_files(p1),
+ alpm_pkg_get_files(dbpkg));
tmpfiles.count = alpm_list_count(difference);
tmpfiles.files = alpm_list_to_array(difference, tmpfiles.count,
sizeof(alpm_file_t));
@@ -493,8 +420,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
int resolved_conflict = 0;
struct stat lsbuf;
char path[PATH_MAX];
+ size_t pathlen;
- snprintf(path, PATH_MAX, "%s%s", handle->root, filestr);
+ pathlen = snprintf(path, PATH_MAX, "%s%s", handle->root, filestr);
/* stat the file - if it exists, do some checks */
if(_alpm_lstat(path, &lsbuf) != 0) {
@@ -518,15 +446,15 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
/* if we made it to here, we want all subsequent path comparisons to
* not include the trailing slash. This allows things like file ->
* directory replacements. */
- path[strlen(path) - 1] = '\0';
+ path[pathlen - 1] = '\0';
}
- relative_path = path + strlen(handle->root);
+ relative_path = path + rootlen;
/* Check remove list (will we remove the conflicting local file?) */
- for(k = remove; k && !resolved_conflict; k = k->next) {
+ for(k = rem; k && !resolved_conflict; k = k->next) {
alpm_pkg_t *rempkg = k->data;
- if(rempkg && _alpm_filelist_contains(alpm_pkg_get_files(rempkg),
+ if(rempkg && alpm_filelist_contains(alpm_pkg_get_files(rempkg),
relative_path)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"local file will be removed, not a conflict\n");
@@ -543,7 +471,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
alpm_pkg_t *localp2 = _alpm_db_get_pkgfromcache(handle->db_local, p2->name);
/* localp2->files will be removed (target conflicts are handled by CHECK 1) */
- if(localp2 && _alpm_filelist_contains(alpm_pkg_get_files(localp2), filestr)) {
+ if(localp2 && alpm_filelist_contains(alpm_pkg_get_files(localp2), filestr)) {
/* skip removal of file, but not add. this will prevent a second
* package from removing the file when it was already installed
* by its new owner (whether the file is in backup array or not */
@@ -559,7 +487,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
if(!resolved_conflict && S_ISDIR(lsbuf.st_mode) && dbpkg) {
char *dir = malloc(strlen(filestr) + 2);
sprintf(dir, "%s/", filestr);
- if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), dir)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(dbpkg), dir)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"checking if all files in %s belong to %s\n",
dir, dbpkg->name);
@@ -573,17 +501,15 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
* consideration cannot itself be a link, as it might be unowned- path
* components can be safely checked as all directories are "unowned". */
if(!resolved_conflict && dbpkg && !S_ISLNK(lsbuf.st_mode)) {
- char *rpath = calloc(PATH_MAX, sizeof(char));
- const char *relative_rpath;
+ char rpath[PATH_MAX];
if(realpath(path, rpath)) {
- relative_rpath = rpath + strlen(handle->root);
- if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) {
+ const char *relative_rpath = rpath + rootlen;
+ if(alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"package contained the resolved realpath\n");
resolved_conflict = 1;
}
}
- free(rpath);
}
/* is the file unowned and in the backup list of the new package? */
@@ -591,7 +517,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
alpm_list_t *local_pkgs = _alpm_db_get_pkgcache(handle->db_local);
int found = 0;
for(k = local_pkgs; k && !found; k = k->next) {
- if(_alpm_filelist_contains(alpm_pkg_get_files(k->data), filestr)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(k->data), filestr)) {
found = 1;
}
}
@@ -607,7 +533,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
if(handle->pm_errno == ALPM_ERR_MEMORY) {
FREELIST(conflicts);
if(dbpkg) {
- /* only freed if it was generated from filelist_operation() */
+ /* only freed if it was generated from _alpm_filelist_difference() */
free(tmpfiles.files);
}
return NULL;
@@ -615,7 +541,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
}
}
if(dbpkg) {
- /* only freed if it was generated from filelist_operation() */
+ /* only freed if it was generated from _alpm_filelist_difference() */
free(tmpfiles.files);
}
}