diff options
Diffstat (limited to 'lib/libalpm/conflict.c')
-rw-r--r-- | lib/libalpm/conflict.c | 89 |
1 files changed, 53 insertions, 36 deletions
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index ad689dcf..8cf16191 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -34,6 +34,7 @@ /* libalpm */ #include "conflict.h" #include "alpm_list.h" +#include "alpm.h" #include "handle.h" #include "trans.h" #include "util.h" @@ -222,6 +223,7 @@ 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. @@ -234,8 +236,10 @@ static alpm_list_t *filelist_operation(alpm_list_t *filesA, alpm_list_t *filesB, alpm_list_t *pA = filesA, *pB = filesB; while(pA && pB) { - const char *strA = pA->data; - const char *strB = pB->data; + alpm_file_t *fileA = pA->data; + alpm_file_t *fileB = pB->data; + const char *strA = fileA->name; + const char *strB = fileB->name; /* skip directories, we don't care about them */ if(strA[strlen(strA)-1] == '/') { pA = pA->next; @@ -246,7 +250,7 @@ static alpm_list_t *filelist_operation(alpm_list_t *filesA, alpm_list_t *filesB, if(cmp < 0) { if(operation == DIFFERENCE) { /* item only in filesA, qualifies as a difference */ - ret = alpm_list_add(ret, strdup(strA)); + ret = alpm_list_add(ret, fileA); } pA = pA->next; } else if(cmp > 0) { @@ -254,7 +258,7 @@ static alpm_list_t *filelist_operation(alpm_list_t *filesA, alpm_list_t *filesB, } else { if(operation == INTERSECT) { /* item in both, qualifies as an intersect */ - ret = alpm_list_add(ret, strdup(strA)); + ret = alpm_list_add(ret, fileA); } pA = pA->next; pB = pB->next; @@ -264,10 +268,11 @@ static alpm_list_t *filelist_operation(alpm_list_t *filesA, alpm_list_t *filesB, /* if doing a difference, ensure we have completely emptied pA */ while(operation == DIFFERENCE && pA) { - const char *strA = pA->data; + alpm_file_t *fileA = pA->data; + const char *strA = fileA->name; /* skip directories */ if(strA[strlen(strA)-1] != '/') { - ret = alpm_list_add(ret, strdup(strA)); + ret = alpm_list_add(ret, fileA); } pA = pA->next; } @@ -314,13 +319,27 @@ void _alpm_fileconflict_free(alpm_fileconflict_t *conflict) FREE(conflict); } +const alpm_file_t *_alpm_filelist_contains(const alpm_list_t *haystack, + const char *needle) +{ + const alpm_list_t *lp = haystack; + while(lp) { + const alpm_file_t *file = lp->data; + if(strcmp(file->name, needle) == 0) { + return file; + } + lp = lp->next; + } + return NULL; +} + static int dir_belongsto_pkg(const char *root, const char *dirpath, alpm_pkg_t *pkg) { - struct dirent *ent = NULL; struct stat sbuf; char path[PATH_MAX]; char abspath[PATH_MAX]; + struct dirent *ent = NULL; DIR *dir; snprintf(abspath, PATH_MAX, "%s%s", root, dirpath); @@ -328,6 +347,7 @@ static int dir_belongsto_pkg(const char *root, const char *dirpath, if(dir == NULL) { return 1; } + while((ent = readdir(dir)) != NULL) { const char *name = ent->d_name; @@ -347,7 +367,7 @@ static int dir_belongsto_pkg(const char *root, const char *dirpath, return 0; } } else { - if(alpm_list_find_str(alpm_pkg_get_files(pkg), path)) { + if(_alpm_filelist_contains(alpm_pkg_get_files(pkg), path)) { continue; } else { closedir(dir); @@ -365,7 +385,7 @@ static int dir_belongsto_pkg(const char *root, const char *dirpath, alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, alpm_list_t *upgrade, alpm_list_t *remove) { - alpm_list_t *i, *j, *conflicts = NULL; + alpm_list_t *i, *conflicts = NULL; size_t numtargs = alpm_list_count(upgrade); size_t current; alpm_trans_t *trans = handle->trans; @@ -379,14 +399,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, * here as we do when we actually extract files in add.c with our 12 * different cases. */ for(current = 0, i = upgrade; i; i = i->next, current++) { - alpm_list_t *k, *tmpfiles; - alpm_pkg_t *p1, *p2, *dbpkg; - char path[PATH_MAX]; - - p1 = i->data; - if(!p1) { - continue; - } + alpm_pkg_t *p1 = i->data; + alpm_list_t *j, *tmpfiles; + alpm_pkg_t *dbpkg; int percent = (current * 100) / numtargs; PROGRESS(trans, ALPM_TRANS_PROGRESS_CONFLICTS_START, "", percent, @@ -396,14 +411,13 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, alpm_pkg_get_name(p1)); for(j = i->next; j; j = j->next) { alpm_list_t *common_files; - p2 = j->data; - if(!p2) { - continue; - } + alpm_pkg_t *p2 = j->data; common_files = filelist_operation(alpm_pkg_get_files(p1), alpm_pkg_get_files(p2), INTERSECT); if(common_files) { + alpm_list_t *k; + char path[PATH_MAX]; for(k = common_files; k; k = k->next) { snprintf(path, PATH_MAX, "%s%s", handle->root, (char *)k->data); conflicts = add_fileconflict(handle, conflicts, @@ -415,7 +429,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, return NULL; } } - FREELIST(common_files); + alpm_list_free(common_files); } } @@ -439,10 +453,14 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, } for(j = tmpfiles; j; j = j->next) { - struct stat lsbuf; - const char *filestr = j->data, *relative_path; + alpm_file_t *file = j->data; + const char *filestr = file->name; + const char *relative_path; + alpm_list_t *k; /* have we acted on this conflict? */ int resolved_conflict = 0; + struct stat lsbuf; + char path[PATH_MAX]; snprintf(path, PATH_MAX, "%s%s", handle->root, filestr); @@ -451,7 +469,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, continue; } - if(path[strlen(path) - 1] == '/') { + if(S_ISDIR(file->mode)) { struct stat sbuf; if(S_ISDIR(lsbuf.st_mode)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); @@ -475,32 +493,31 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, /* Check remove list (will we remove the conflicting local file?) */ for(k = remove; k && !resolved_conflict; k = k->next) { alpm_pkg_t *rempkg = k->data; - if(alpm_list_find_str(alpm_pkg_get_files(rempkg), relative_path)) { + 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: %s\n", - relative_path); + "local file will be removed, not a conflict: %s\n", path); resolved_conflict = 1; } } /* Look at all the targets to see if file has changed hands */ for(k = upgrade; k && !resolved_conflict; k = k->next) { - p2 = k->data; + alpm_pkg_t *p2 = k->data; if(!p2 || strcmp(p1->name, p2->name) == 0) { continue; } 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_list_find_str(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 */ handle->trans->skip_remove = alpm_list_add(handle->trans->skip_remove, strdup(filestr)); _alpm_log(handle, ALPM_LOG_DEBUG, - "file changed packages, adding to remove skiplist: %s\n", - filestr); + "file changed packages, adding to remove skiplist: %s\n", path); resolved_conflict = 1; } } @@ -509,7 +526,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_list_find_str(alpm_pkg_get_files(dbpkg),dir)) { + 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", dir, dbpkg->name); @@ -526,7 +543,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, continue; } relative_rpath = rpath + strlen(handle->root); - if(alpm_list_find_str(alpm_pkg_get_files(dbpkg), relative_rpath)) { + if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) { resolved_conflict = 1; } free(rpath); @@ -539,7 +556,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, FREELIST(conflicts); if(dbpkg) { /* only freed if it was generated from filelist_operation() */ - FREELIST(tmpfiles); + alpm_list_free(tmpfiles); } return NULL; } @@ -547,7 +564,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, } if(dbpkg) { /* only freed if it was generated from filelist_operation() */ - FREELIST(tmpfiles); + alpm_list_free(tmpfiles); } } PROGRESS(trans, ALPM_TRANS_PROGRESS_CONFLICTS_START, "", 100, |