diff options
Diffstat (limited to 'lib/libalpm/conflict.c')
-rw-r--r-- | lib/libalpm/conflict.c | 545 |
1 files changed, 256 insertions, 289 deletions
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c index db10d329..538c4c73 100644 --- a/lib/libalpm/conflict.c +++ b/lib/libalpm/conflict.c @@ -34,29 +34,28 @@ /* libalpm */ #include "conflict.h" #include "alpm_list.h" +#include "alpm.h" #include "handle.h" #include "trans.h" #include "util.h" #include "log.h" #include "deps.h" -pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2, +static alpm_conflict_t *conflict_new(const char *package1, const char *package2, const char *reason) { - pmconflict_t *conflict; + alpm_conflict_t *conflict; - ALPM_LOG_FUNC; + MALLOC(conflict, sizeof(alpm_conflict_t), return NULL); - MALLOC(conflict, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->package1, package1, return NULL); + STRDUP(conflict->package2, package2, return NULL); + STRDUP(conflict->reason, reason, return NULL); - STRDUP(conflict->package1, package1, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(conflict->package2, package2, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(conflict->reason, reason, RET_ERR(PM_ERR_MEMORY, NULL)); - - return(conflict); + return conflict; } -void _alpm_conflict_free(pmconflict_t *conflict) +void _alpm_conflict_free(alpm_conflict_t *conflict) { FREE(conflict->package2); FREE(conflict->package1); @@ -64,55 +63,59 @@ void _alpm_conflict_free(pmconflict_t *conflict) FREE(conflict); } -pmconflict_t *_alpm_conflict_dup(const pmconflict_t *conflict) +alpm_conflict_t *_alpm_conflict_dup(const alpm_conflict_t *conflict) { - pmconflict_t *newconflict; - CALLOC(newconflict, 1, sizeof(pmconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + alpm_conflict_t *newconflict; + CALLOC(newconflict, 1, sizeof(alpm_conflict_t), return NULL); - STRDUP(newconflict->package1, conflict->package1, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(newconflict->package2, conflict->package2, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(newconflict->reason, conflict->reason, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(newconflict->package1, conflict->package1, return NULL); + STRDUP(newconflict->package2, conflict->package2, return NULL); + STRDUP(newconflict->reason, conflict->reason, return NULL); - return(newconflict); + return newconflict; } -static int conflict_isin(pmconflict_t *needle, alpm_list_t *haystack) +static int conflict_isin(alpm_conflict_t *needle, alpm_list_t *haystack) { alpm_list_t *i; const char *npkg1 = needle->package1; const char *npkg2 = needle->package2; - ALPM_LOG_FUNC; - for(i = haystack; i; i = i->next) { - pmconflict_t *conflict = i->data; + alpm_conflict_t *conflict = i->data; const char *cpkg1 = conflict->package1; const char *cpkg2 = conflict->package2; if((strcmp(cpkg1, npkg1) == 0 && strcmp(cpkg2, npkg2) == 0) || (strcmp(cpkg1, npkg2) == 0 && strcmp(cpkg2, npkg1) == 0)) { - return(1); + return 1; } } - return(0); + return 0; } -/** Adds the pkg1/pkg2 conflict to the baddeps list - * @param *baddeps list to add conflict to +/** Adds the pkg1/pkg2 conflict to the baddeps list. + * @param handle the context handle + * @param baddeps list to add conflict to * @param pkg1 first package * @param pkg2 package causing conflict + * @param reason reason for this conflict */ -static void add_conflict(alpm_list_t **baddeps, const char *pkg1, - const char *pkg2, const char *reason) +static int add_conflict(alpm_handle_t *handle, alpm_list_t **baddeps, + const char *pkg1, const char *pkg2, const char *reason) { - pmconflict_t *conflict = _alpm_conflict_new(pkg1, pkg2, reason); - _alpm_log(PM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n", + alpm_conflict_t *conflict = conflict_new(pkg1, pkg2, reason); + if(!conflict) { + return -1; + } + _alpm_log(handle, ALPM_LOG_DEBUG, "package %s conflicts with %s (by %s)\n", pkg1, pkg2, reason); - if(conflict && !conflict_isin(conflict, *baddeps)) { + if(!conflict_isin(conflict, *baddeps)) { *baddeps = alpm_list_add(*baddeps, conflict); } else { _alpm_conflict_free(conflict); } + return 0; } /** Check if packages from list1 conflict with packages from list2. @@ -121,28 +124,32 @@ static void add_conflict(alpm_list_t **baddeps, const char *pkg1, * If a conflict (pkg1, pkg2) is found, it is added to the baddeps list * in this order if order >= 0, or reverse order (pkg2,pkg1) otherwise. * + * @param handle the context handle * @param list1 first list of packages * @param list2 second list of packages - * @param *baddeps list to store conflicts + * @param baddeps list to store conflicts * @param order if >= 0 the conflict order is preserved, if < 0 it's reversed */ -static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, +static void check_conflict(alpm_handle_t *handle, + alpm_list_t *list1, alpm_list_t *list2, alpm_list_t **baddeps, int order) { - alpm_list_t *i, *j, *k; + alpm_list_t *i; if(!baddeps) { return; } for(i = list1; i; i = i->next) { - pmpkg_t *pkg1 = i->data; + alpm_pkg_t *pkg1 = i->data; const char *pkg1name = alpm_pkg_get_name(pkg1); + alpm_list_t *j; for(j = alpm_pkg_get_conflicts(pkg1); j; j = j->next) { const char *conflict = j->data; - pmdepend_t *parsed_conflict = _alpm_splitdep(conflict); + alpm_list_t *k; + alpm_depend_t *parsed_conflict = _alpm_splitdep(conflict); for(k = list2; k; k = k->next) { - pmpkg_t *pkg2 = k->data; + alpm_pkg_t *pkg2 = k->data; const char *pkg2name = alpm_pkg_get_name(pkg2); if(strcmp(pkg1name, pkg2name) == 0) { @@ -152,9 +159,9 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, if(_alpm_depcmp(pkg2, parsed_conflict)) { if(order >= 0) { - add_conflict(baddeps, pkg1name, pkg2name, conflict); + add_conflict(handle, baddeps, pkg1name, pkg2name, conflict); } else { - add_conflict(baddeps, pkg2name, pkg1name, conflict); + add_conflict(handle, baddeps, pkg2name, pkg1name, conflict); } } } @@ -164,189 +171,183 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2, } /* Check for inter-conflicts */ -alpm_list_t *_alpm_innerconflicts(alpm_list_t *packages) +alpm_list_t *_alpm_innerconflicts(alpm_handle_t *handle, alpm_list_t *packages) { alpm_list_t *baddeps = NULL; - ALPM_LOG_FUNC; - - _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n"); - check_conflict(packages, packages, &baddeps, 0); + _alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs targets\n"); + check_conflict(handle, packages, packages, &baddeps, 0); - return(baddeps); + return baddeps; } /* Check for target vs (db - target) conflicts * In case of conflict the package1 field of pmdepconflict_t contains * the target package, package2 field contains the local package */ -alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages) +alpm_list_t *_alpm_outerconflicts(alpm_db_t *db, alpm_list_t *packages) { alpm_list_t *baddeps = NULL; - ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); + return NULL; } alpm_list_t *dblist = alpm_list_diff(_alpm_db_get_pkgcache(db), packages, _alpm_pkg_cmp); /* two checks to be done here for conflicts */ - _alpm_log(PM_LOG_DEBUG, "check targets vs db\n"); - check_conflict(packages, dblist, &baddeps, 1); - _alpm_log(PM_LOG_DEBUG, "check db vs targets\n"); - check_conflict(dblist, packages, &baddeps, -1); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "check targets vs db\n"); + check_conflict(db->handle, packages, dblist, &baddeps, 1); + _alpm_log(db->handle, ALPM_LOG_DEBUG, "check db vs targets\n"); + check_conflict(db->handle, dblist, packages, &baddeps, -1); alpm_list_free(dblist); - return(baddeps); + return baddeps; } /** Check the package conflicts in a database * + * @param handle the context handle * @param pkglist the list of packages to check - * @return an alpm_list_t of pmconflict_t + * @return an alpm_list_t of alpm_conflict_t */ -alpm_list_t SYMEXPORT *alpm_checkconflicts(alpm_list_t *pkglist) { - return(_alpm_innerconflicts(pkglist)); -} - -/* Returns a alpm_list_t* of file conflicts. - * Hooray for set-intersects! - * Pre-condition: both lists are sorted! - */ -static alpm_list_t *chk_fileconflicts(alpm_list_t *filesA, alpm_list_t *filesB) +alpm_list_t SYMEXPORT *alpm_checkconflicts(alpm_handle_t *handle, + alpm_list_t *pkglist) { - alpm_list_t *ret = NULL; - alpm_list_t *pA = filesA, *pB = filesB; - - while(pA && pB) { - const char *strA = pA->data; - const char *strB = pB->data; - /* skip directories, we don't care about dir conflicts */ - if(strA[strlen(strA)-1] == '/') { - pA = pA->next; - } else if(strB[strlen(strB)-1] == '/') { - pB = pB->next; - } else { - int cmp = strcmp(strA, strB); - if(cmp < 0) { - /* item only in filesA, ignore it */ - pA = pA->next; - } else if(cmp > 0) { - /* item only in filesB, ignore it */ - pB = pB->next; - } else { - /* item in both, record it */ - ret = alpm_list_add(ret, strdup(strA)); - pA = pA->next; - pB = pB->next; - } - } - } - - return(ret); + CHECK_HANDLE(handle, return NULL); + return _alpm_innerconflicts(handle, pkglist); } -/* Returns a alpm_list_t* of files that are in filesA but *NOT* in filesB - * This is an 'A minus B' set operation - * Pre-condition: both lists are sorted! +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 *chk_filedifference(alpm_list_t *filesA, alpm_list_t *filesB) +static alpm_list_t *filelist_operation(alpm_filelist_t *filesA, + alpm_filelist_t *filesB, int operation) { alpm_list_t *ret = NULL; - alpm_list_t *pA = filesA, *pB = filesB; - - /* if both filesA and filesB have entries, do this loop */ - while(pA && pB) { - const char *strA = pA->data; - const char *strB = pB->data; - /* skip directories, we don't care about dir conflicts */ + 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] == '/') { - pA = pA->next; + ctrA++; } else if(strB[strlen(strB)-1] == '/') { - pB = pB->next; + ctrB++; } else { int cmp = strcmp(strA, strB); if(cmp < 0) { - /* item only in filesA, record it */ - ret = alpm_list_add(ret, strdup(strA)); - pA = pA->next; + if(operation == DIFFERENCE) { + /* item only in filesA, qualifies as a difference */ + ret = alpm_list_add(ret, fileA); + } + ctrA++; } else if(cmp > 0) { - /* item only in fileB, but this means nothing */ - pB = pB->next; + ctrB++; } else { - /* item in both, ignore it */ - pA = pA->next; - pB = pB->next; + if(operation == INTERSECT) { + /* item in both, qualifies as an intersect */ + ret = alpm_list_add(ret, fileA); + } + ctrA++; + ctrB++; } } } - /* ensure we have completely emptied pA */ - while(pA) { - const char *strA = pA->data; + + /* 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, strdup(strA)); + ret = alpm_list_add(ret, fileA); } - pA = pA->next; + ctrA++; } - return(ret); + return ret; } -/* Adds pmfileconflict_t to a conflicts list. Pass the conflicts list, type - * (either PM_FILECONFLICT_TARGET or PM_FILECONFLICT_FILESYSTEM), a file +/* Adds alpm_fileconflict_t to a conflicts list. Pass the conflicts list, type + * (either ALPM_FILECONFLICT_TARGET or ALPM_FILECONFLICT_FILESYSTEM), a file * string, and either two package names or one package name and NULL. This is * a wrapper for former functionality that was done inline. */ -static alpm_list_t *add_fileconflict(alpm_list_t *conflicts, - pmfileconflicttype_t type, const char *filestr, - const char *name1, const char *name2) +static alpm_list_t *add_fileconflict(alpm_handle_t *handle, + alpm_list_t *conflicts, alpm_fileconflicttype_t type, const char *filestr, + const char *name1, const char *name2) { - pmfileconflict_t *conflict; - MALLOC(conflict, sizeof(pmfileconflict_t), RET_ERR(PM_ERR_MEMORY, NULL)); + alpm_fileconflict_t *conflict; + MALLOC(conflict, sizeof(alpm_fileconflict_t), goto error); conflict->type = type; - STRDUP(conflict->target, name1, RET_ERR(PM_ERR_MEMORY, NULL)); - STRDUP(conflict->file, filestr, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->target, name1, goto error); + STRDUP(conflict->file, filestr, goto error); if(name2) { - STRDUP(conflict->ctarget, name2, RET_ERR(PM_ERR_MEMORY, NULL)); + STRDUP(conflict->ctarget, name2, goto error); } else { - conflict->ctarget = ""; + STRDUP(conflict->ctarget, "", goto error); } conflicts = alpm_list_add(conflicts, conflict); - _alpm_log(PM_LOG_DEBUG, "found file conflict %s, packages %s and %s\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "found file conflict %s, packages %s and %s\n", filestr, name1, name2 ? name2 : "(filesystem)"); - return(conflicts); + return conflicts; + +error: + RET_ERR(handle, ALPM_ERR_MEMORY, conflicts); } -void _alpm_fileconflict_free(pmfileconflict_t *conflict) +void _alpm_fileconflict_free(alpm_fileconflict_t *conflict) { - if(strlen(conflict->ctarget) > 0) { - FREE(conflict->ctarget); - } - FREE(conflict->file);; + FREE(conflict->ctarget); + FREE(conflict->file); FREE(conflict->target); FREE(conflict); } -static int dir_belongsto_pkg(const char *dirpath, pmpkg_t *pkg) +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(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", handle->root, dirpath); + snprintf(abspath, PATH_MAX, "%s%s", root, dirpath); dir = opendir(abspath); if(dir == NULL) { - return(1); + return 1; } + while((ent = readdir(dir)) != NULL) { const char *name = ent->d_name; @@ -354,44 +355,43 @@ static int dir_belongsto_pkg(const char *dirpath, pmpkg_t *pkg) continue; } snprintf(path, PATH_MAX, "%s/%s", dirpath, name); - snprintf(abspath, PATH_MAX, "%s%s", handle->root, path); + snprintf(abspath, PATH_MAX, "%s%s", root, path); if(stat(abspath, &sbuf) != 0) { continue; } if(S_ISDIR(sbuf.st_mode)) { - if(dir_belongsto_pkg(path, pkg)) { + if(dir_belongsto_pkg(root, path, pkg)) { continue; } else { closedir(dir); - return(0); + 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); - return(0); + return 0; } } } closedir(dir); - return(1); + 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 */ -alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, +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; - ALPM_LOG_FUNC; - - if(db == NULL || upgrade == NULL || trans == NULL) { - return(NULL); + if(!upgrade) { + return NULL; } /* TODO this whole function needs a huge change, which hopefully will @@ -399,61 +399,75 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, * 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 = NULL; - pmpkg_t *p1, *p2, *dbpkg; - char path[PATH_MAX+1]; - - p1 = i->data; - if(!p1) { - continue; - } + alpm_pkg_t *p1 = i->data; + alpm_list_t *j; + alpm_filelist_t tmpfiles; + alpm_pkg_t *dbpkg; + size_t filenum; int percent = (current * 100) / numtargs; - PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", percent, + PROGRESS(trans, ALPM_TRANS_PROGRESS_CONFLICTS_START, "", percent, numtargs, current); /* CHECK 1: check every target against every target */ - _alpm_log(PM_LOG_DEBUG, "searching for file conflicts: %s\n", + _alpm_log(handle, ALPM_LOG_DEBUG, "searching for file conflicts: %s\n", alpm_pkg_get_name(p1)); for(j = i->next; j; j = j->next) { - p2 = j->data; - if(!p2) { - continue; - } - tmpfiles = chk_fileconflicts(alpm_pkg_get_files(p1), alpm_pkg_get_files(p2)); - - if(tmpfiles) { - for(k = tmpfiles; k; k = k->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); + + 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(conflicts, PM_FILECONFLICT_TARGET, path, + conflicts = add_fileconflict(handle, conflicts, + ALPM_FILECONFLICT_TARGET, path, alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)); + if(handle->pm_errno == ALPM_ERR_MEMORY) { + FREELIST(conflicts); + FREELIST(common_files); + return NULL; + } } - FREELIST(tmpfiles); + alpm_list_free(common_files); } } - /* declarations for second check */ - struct stat lsbuf, sbuf; - /* CHECK 2: check every target against the filesystem */ - _alpm_log(PM_LOG_DEBUG, "searching for filesystem conflicts: %s\n", p1->name); - dbpkg = _alpm_db_get_pkgfromcache(db, p1->name); + _alpm_log(handle, ALPM_LOG_DEBUG, "searching for filesystem conflicts: %s\n", + p1->name); + dbpkg = _alpm_db_get_pkgfromcache(handle->db_local, p1->name); /* Do two different checks here. If the package is currently installed, * then only check files that are new in the new package. If the package - * is not currently installed, then simply stat the whole filelist */ + * is not currently installed, then simply stat the whole filelist. Note + * that the former list needs to be freed while the latter list should NOT + * be freed. */ if(dbpkg) { + alpm_list_t *difference; /* older ver of package currently installed */ - tmpfiles = chk_filedifference(alpm_pkg_get_files(p1), - alpm_pkg_get_files(dbpkg)); + difference = filelist_operation(alpm_pkg_get_files(p1), + alpm_pkg_get_files(dbpkg), DIFFERENCE); + tmpfiles.count = alpm_list_count(difference); + tmpfiles.files = alpm_list_to_array(difference, tmpfiles.count, + sizeof(alpm_file_t)); + alpm_list_free(difference); } else { /* no version of package currently installed */ - tmpfiles = alpm_list_strdup(alpm_pkg_get_files(p1)); + tmpfiles = *alpm_pkg_get_files(p1); } - for(j = tmpfiles; j; j = j->next) { - const char *filestr = j->data, *relative_path; + for(filenum = 0; filenum < tmpfiles.count; filenum++) { + alpm_file_t *file = tmpfiles.files + filenum; + 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); @@ -461,14 +475,16 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, if(_alpm_lstat(path, &lsbuf) != 0) { continue; } - stat(path, &sbuf); - if(path[strlen(path) - 1] == '/') { + if(S_ISDIR(file->mode)) { + struct stat sbuf; if(S_ISDIR(lsbuf.st_mode)) { - _alpm_log(PM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); + _alpm_log(handle, ALPM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); continue; - } else if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(sbuf.st_mode)) { - _alpm_log(PM_LOG_DEBUG, + } + stat(path, &sbuf); + if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(sbuf.st_mode)) { + _alpm_log(handle, ALPM_LOG_DEBUG, "%s is a symlink to a dir, hopefully not a conflict\n", path); continue; } @@ -478,38 +494,37 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, path[strlen(path) - 1] = '\0'; } - _alpm_log(PM_LOG_DEBUG, "checking possible conflict: %s\n", path); + _alpm_log(handle, ALPM_LOG_DEBUG, "checking possible conflict: %s\n", path); relative_path = path + strlen(handle->root); /* Check remove list (will we remove the conflicting local file?) */ for(k = remove; k && !resolved_conflict; k = k->next) { - pmpkg_t *rempkg = k->data; - if(alpm_list_find_str(alpm_pkg_get_files(rempkg), relative_path)) { - _alpm_log(PM_LOG_DEBUG, - "local file will be removed, not a conflict: %s\n", - relative_path); + alpm_pkg_t *rempkg = k->data; + 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", 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; } - pmpkg_t *localp2 = _alpm_db_get_pkgfromcache(db, p2->name); + 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 */ - trans->skip_remove = alpm_list_add(trans->skip_remove, - strdup(filestr)); - _alpm_log(PM_LOG_DEBUG, - "file changed packages, adding to remove skiplist: %s\n", - filestr); + 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", path); resolved_conflict = 1; } } @@ -518,115 +533,67 @@ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, 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", + 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); - resolved_conflict = dir_belongsto_pkg(filestr, dbpkg); + resolved_conflict = dir_belongsto_pkg(handle->root, filestr, dbpkg); } free(dir); } if(!resolved_conflict && dbpkg) { - char *rpath = calloc(PATH_MAX+1, sizeof(char)); + char *rpath = calloc(PATH_MAX, sizeof(char)); const char *relative_rpath; if(!realpath(path, rpath)) { free(rpath); 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); } + /* is the file unowned and in the backup list of the new package? */ + if(!resolved_conflict && _alpm_needbackup(filestr, p1)) { + 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)) { + found = 1; + } + } + if(!found) { + _alpm_log(handle, ALPM_LOG_DEBUG, + "file was unowned but in new backup list: %s\n", path); + resolved_conflict = 1; + } + } + if(!resolved_conflict) { - conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_FILESYSTEM, - path, p1->name, NULL); + conflicts = add_fileconflict(handle, conflicts, + ALPM_FILECONFLICT_FILESYSTEM, path, p1->name, NULL); + if(handle->pm_errno == ALPM_ERR_MEMORY) { + FREELIST(conflicts); + if(dbpkg) { + /* only freed if it was generated from filelist_operation() */ + free(tmpfiles.files); + } + return NULL; + } } } - FREELIST(tmpfiles); + if(dbpkg) { + /* only freed if it was generated from filelist_operation() */ + free(tmpfiles.files); + } } - PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", 100, + PROGRESS(trans, ALPM_TRANS_PROGRESS_CONFLICTS_START, "", 100, numtargs, current); - return(conflicts); + return conflicts; } -const char SYMEXPORT *alpm_conflict_get_package1(pmconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->package1; -} - -const char SYMEXPORT *alpm_conflict_get_package2(pmconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->package2; -} - -const char SYMEXPORT *alpm_conflict_get_reason(pmconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->reason; -} - -const char SYMEXPORT *alpm_fileconflict_get_target(pmfileconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->target; -} - -pmfileconflicttype_t SYMEXPORT alpm_fileconflict_get_type(pmfileconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(-1)); - ASSERT(conflict != NULL, return(-1)); - - return conflict->type; -} - -const char SYMEXPORT *alpm_fileconflict_get_file(pmfileconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->file; -} - -const char SYMEXPORT *alpm_fileconflict_get_ctarget(pmfileconflict_t *conflict) -{ - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, return(NULL)); - ASSERT(conflict != NULL, return(NULL)); - - return conflict->ctarget; -} /* vim: set ts=2 sw=2 noet: */ |