diff options
-rw-r--r-- | lib/libalpm/alpm.h | 7 | ||||
-rw-r--r-- | lib/libalpm/alpm_list.c | 18 | ||||
-rw-r--r-- | lib/libalpm/alpm_list.h | 1 | ||||
-rw-r--r-- | lib/libalpm/be_local.c | 133 | ||||
-rw-r--r-- | lib/libalpm/be_package.c | 14 | ||||
-rw-r--r-- | lib/libalpm/be_sync.c | 24 | ||||
-rw-r--r-- | lib/libalpm/conflict.c | 89 | ||||
-rw-r--r-- | lib/libalpm/conflict.h | 3 | ||||
-rw-r--r-- | lib/libalpm/deps.c | 6 | ||||
-rw-r--r-- | lib/libalpm/diskspace.c | 55 | ||||
-rw-r--r-- | lib/libalpm/dload.c | 2 | ||||
-rw-r--r-- | lib/libalpm/package.c | 38 | ||||
-rw-r--r-- | lib/libalpm/package.h | 4 | ||||
-rw-r--r-- | lib/libalpm/remove.c | 41 | ||||
-rw-r--r-- | src/pacman/package.c | 8 | ||||
-rw-r--r-- | src/pacman/query.c | 6 | ||||
-rw-r--r-- | test/pacman/tests/fileconflict001.py | 3 | ||||
-rw-r--r-- | test/pacman/tests/fileconflict002.py | 9 |
18 files changed, 244 insertions, 217 deletions
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 8d458c3e..e733eb2d 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -160,6 +160,13 @@ typedef struct _alpm_delta_t { off_t download_size; } alpm_delta_t; +/** File in a package */ +typedef struct _alpm_file_t { + char *name; + off_t size; + mode_t mode; +} alpm_file_t; + /** Local package or package file backup entry */ typedef struct _alpm_backup_t { char *name; diff --git a/lib/libalpm/alpm_list.c b/lib/libalpm/alpm_list.c index c2b30adc..1976e13d 100644 --- a/lib/libalpm/alpm_list.c +++ b/lib/libalpm/alpm_list.c @@ -556,6 +556,24 @@ inline alpm_list_t SYMEXPORT *alpm_list_next(const alpm_list_t *node) } /** + * @brief Get the previous element of a list. + * + * @param list the list head + * @param node the list node + * + * @return the previous element, or NULL when no previous element exist + */ +inline alpm_list_t SYMEXPORT *alpm_list_previous(const alpm_list_t *list, + const alpm_list_t *node) +{ + if(node && node != list) { + return node->prev; + } else { + return NULL; + } +} + +/** * @brief Get the last item in the list. * * @param list the list diff --git a/lib/libalpm/alpm_list.h b/lib/libalpm/alpm_list.h index 1f6393a6..27a76d12 100644 --- a/lib/libalpm/alpm_list.h +++ b/lib/libalpm/alpm_list.h @@ -70,6 +70,7 @@ alpm_list_t *alpm_list_reverse(alpm_list_t *list); alpm_list_t *alpm_list_first(const alpm_list_t *list); alpm_list_t *alpm_list_nth(const alpm_list_t *list, size_t n); alpm_list_t *alpm_list_next(const alpm_list_t *list); +alpm_list_t *alpm_list_previous(const alpm_list_t *list, const alpm_list_t *node); alpm_list_t *alpm_list_last(const alpm_list_t *list); void *alpm_list_getdata(const alpm_list_t *entry); diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 304a5a13..70f242d2 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -498,6 +498,23 @@ static char *get_pkgpath(alpm_db_t *db, alpm_pkg_t *info) return pkgpath; } +#define READ_NEXT() do { \ + if(fgets(line, sizeof(line), fp) == NULL && !feof(fp)) goto error; \ + _alpm_strtrim(line); \ +} while(0) + +#define READ_AND_STORE(f) do { \ + READ_NEXT(); \ + STRDUP(f, line, goto error); \ +} while(0) + +#define READ_AND_STORE_ALL(f) do { \ + char *linedup; \ + READ_NEXT(); \ + if(strlen(line) == 0) break; \ + STRDUP(linedup, line, goto error); \ + f = alpm_list_add(f, linedup); \ +} while(1) /* note the while(1) and not (0) */ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) { @@ -539,116 +556,65 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) goto error; } while(!feof(fp)) { - if(fgets(line, sizeof(line), fp) == NULL) { - break; - } - _alpm_strtrim(line); + READ_NEXT(); if(strcmp(line, "%NAME%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - if(strcmp(_alpm_strtrim(line), info->name) != 0) { + READ_NEXT(); + if(strcmp(line, info->name) != 0) { _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: name " "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%VERSION%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - if(strcmp(_alpm_strtrim(line), info->version) != 0) { + READ_NEXT(); + if(strcmp(line, info->version) != 0) { _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: version " "mismatch on package %s\n"), db->treename, info->name); } } else if(strcmp(line, "%DESC%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - STRDUP(info->desc, _alpm_strtrim(line), goto error); + READ_AND_STORE(info->desc); } else if(strcmp(line, "%GROUPS%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->groups = alpm_list_add(info->groups, linedup); - } + READ_AND_STORE_ALL(info->groups); } else if(strcmp(line, "%URL%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - STRDUP(info->url, _alpm_strtrim(line), goto error); + READ_AND_STORE(info->url); } else if(strcmp(line, "%LICENSE%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->licenses = alpm_list_add(info->licenses, linedup); - } + READ_AND_STORE_ALL(info->licenses); } else if(strcmp(line, "%ARCH%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - STRDUP(info->arch, _alpm_strtrim(line), goto error); + READ_AND_STORE(info->arch); } else if(strcmp(line, "%BUILDDATE%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - _alpm_strtrim(line); + READ_NEXT(); info->builddate = _alpm_parsedate(line); } else if(strcmp(line, "%INSTALLDATE%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - _alpm_strtrim(line); + READ_NEXT(); info->installdate = _alpm_parsedate(line); } else if(strcmp(line, "%PACKAGER%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - STRDUP(info->packager, _alpm_strtrim(line), goto error); + READ_AND_STORE(info->packager); } else if(strcmp(line, "%REASON%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - info->reason = (alpm_pkgreason_t)atol(_alpm_strtrim(line)); + READ_NEXT(); + info->reason = (alpm_pkgreason_t)atol(line); } else if(strcmp(line, "%SIZE%") == 0) { /* NOTE: the CSIZE and SIZE fields both share the "size" field * in the pkginfo_t struct. This can be done b/c CSIZE * is currently only used in sync databases, and SIZE is * only used in local databases. */ - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - info->size = atol(_alpm_strtrim(line)); + READ_NEXT(); + info->size = atol(line); /* also store this value to isize */ info->isize = info->size; } else if(strcmp(line, "%REPLACES%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->replaces = alpm_list_add(info->replaces, linedup); - } + READ_AND_STORE_ALL(info->replaces); } else if(strcmp(line, "%DEPENDS%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - alpm_depend_t *dep = _alpm_splitdep(line); - info->depends = alpm_list_add(info->depends, dep); + /* Different than the rest because of the _alpm_splitdep call. */ + while(1) { + READ_NEXT(); + if(strlen(line) == 0) break; + info->depends = alpm_list_add(info->depends, _alpm_splitdep(line)); } } else if(strcmp(line, "%OPTDEPENDS%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->optdepends = alpm_list_add(info->optdepends, linedup); - } + READ_AND_STORE_ALL(info->optdepends); } else if(strcmp(line, "%CONFLICTS%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->conflicts = alpm_list_add(info->conflicts, linedup); - } + READ_AND_STORE_ALL(info->conflicts); } else if(strcmp(line, "%PROVIDES%") == 0) { - while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->provides = alpm_list_add(info->provides, linedup); - } + READ_AND_STORE_ALL(info->provides); } } fclose(fp); @@ -666,9 +632,11 @@ static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq) _alpm_strtrim(line); if(strcmp(line, "%FILES%") == 0) { while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { - char *linedup; - STRDUP(linedup, line, goto error); - info->files = alpm_list_add(info->files, linedup); + alpm_file_t *file; + CALLOC(file, 1, sizeof(alpm_file_t), goto error); + STRDUP(file->name, line, goto error); + /* TODO: lstat file, get mode/size */ + info->files = alpm_list_add(info->files, file); } } else if(strcmp(line, "%BACKUP%") == 0) { while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { @@ -869,14 +837,15 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, alpm_dbinfrq_t inforeq if(info->files) { fprintf(fp, "%%FILES%%\n"); for(lp = info->files; lp; lp = lp->next) { - fprintf(fp, "%s\n", (char *)lp->data); + const alpm_file_t *file = lp->data; + fprintf(fp, "%s\n", file->name); } fprintf(fp, "\n"); } if(info->backup) { fprintf(fp, "%%BACKUP%%\n"); for(lp = info->backup; lp; lp = lp->next) { - alpm_backup_t *backup = lp->data; + const alpm_backup_t *backup = lp->data; fprintf(fp, "%s\t%s\n", backup->name, backup->hash); } fprintf(fp, "\n"); diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 16132144..af213241 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -328,7 +328,12 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile, * already been handled (for future possibilities) */ } else if(full) { /* Keep track of all files for filelist generation */ - newpkg->files = alpm_list_add(newpkg->files, strdup(entry_name)); + alpm_file_t *file; + CALLOC(file, 1, sizeof(alpm_file_t), goto error); + STRDUP(file->name, entry_name, goto error); + file->size = archive_entry_size(entry); + file->mode = archive_entry_mode(entry); + newpkg->files = alpm_list_add(newpkg->files, file); files_count++; } @@ -368,11 +373,14 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile, if(full) { /* "checking for conflicts" requires a sorted list, ensure that here */ _alpm_log(handle, ALPM_LOG_DEBUG, "sorting package filelist for %s\n", pkgfile); - newpkg->files = alpm_list_msort(newpkg->files, files_count, _alpm_str_cmp); + newpkg->files = alpm_list_msort(newpkg->files, files_count, + _alpm_files_cmp); newpkg->infolevel = INFRQ_ALL; } else { /* get rid of any partial filelist we may have collected, it is invalid */ - FREELIST(newpkg->files); + alpm_list_free_inner(newpkg->files, (alpm_list_fn_free)_alpm_files_free); + alpm_list_free(newpkg->files); + newpkg->files = NULL; newpkg->infolevel = INFRQ_BASE | INFRQ_DESC; } diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index cda1e097..368accea 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -433,19 +433,19 @@ static int sync_db_populate(alpm_db_t *db) return count; } -#define READ_NEXT(s) do { \ +#define READ_NEXT() do { \ if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \ - s = _alpm_strtrim(buf.line); \ + line = _alpm_strtrim(buf.line); \ } while(0) #define READ_AND_STORE(f) do { \ - READ_NEXT(line); \ + READ_NEXT(); \ STRDUP(f, line, goto error); \ } while(0) #define READ_AND_STORE_ALL(f) do { \ char *linedup; \ - READ_NEXT(line); \ + READ_NEXT(); \ if(strlen(line) == 0) break; \ STRDUP(linedup, line, goto error); \ f = alpm_list_add(f, linedup); \ @@ -488,13 +488,13 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive, char *line = _alpm_strtrim(buf.line); if(strcmp(line, "%NAME%") == 0) { - READ_NEXT(line); + READ_NEXT(); if(strcmp(line, pkg->name) != 0) { _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: name " "mismatch on package %s\n"), db->treename, pkg->name); } } else if(strcmp(line, "%VERSION%") == 0) { - READ_NEXT(line); + READ_NEXT(); if(strcmp(line, pkg->version) != 0) { _alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: version " "mismatch on package %s\n"), db->treename, pkg->name); @@ -512,7 +512,7 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive, } else if(strcmp(line, "%ARCH%") == 0) { READ_AND_STORE(pkg->arch); } else if(strcmp(line, "%BUILDDATE%") == 0) { - READ_NEXT(line); + READ_NEXT(); pkg->builddate = _alpm_parsedate(line); } else if(strcmp(line, "%PACKAGER%") == 0) { READ_AND_STORE(pkg->packager); @@ -521,20 +521,20 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive, * pkginfo_t struct. This can be done b/c CSIZE is currently only used * in sync databases, and SIZE is only used in local databases. */ - READ_NEXT(line); + READ_NEXT(); pkg->size = atol(line); /* also store this value to isize if isize is unset */ if(pkg->isize == 0) { pkg->isize = pkg->size; } } else if(strcmp(line, "%ISIZE%") == 0) { - READ_NEXT(line); + READ_NEXT(); pkg->isize = atol(line); } else if(strcmp(line, "%MD5SUM%") == 0) { READ_AND_STORE(pkg->md5sum); } else if(strcmp(line, "%SHA256SUM%") == 0) { /* we don't do anything with this value right now */ - READ_NEXT(line); + READ_NEXT(); } else if(strcmp(line, "%PGPSIG%") == 0) { READ_AND_STORE(pkg->base64_sig); } else if(strcmp(line, "%REPLACES%") == 0) { @@ -542,7 +542,7 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive, } else if(strcmp(line, "%DEPENDS%") == 0) { /* Different than the rest because of the _alpm_splitdep call. */ while(1) { - READ_NEXT(line); + READ_NEXT(); if(strlen(line) == 0) break; pkg->depends = alpm_list_add(pkg->depends, _alpm_splitdep(line)); } @@ -555,7 +555,7 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive, } else if(strcmp(line, "%DELTAS%") == 0) { /* Different than the rest because of the _alpm_delta_parse call. */ while(1) { - READ_NEXT(line); + READ_NEXT(); if(strlen(line) == 0) break; pkg->deltas = alpm_list_add(pkg->deltas, _alpm_delta_parse(line)); } 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, diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h index 6c13cb28..f2ab6258 100644 --- a/lib/libalpm/conflict.h +++ b/lib/libalpm/conflict.h @@ -33,6 +33,9 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, void _alpm_fileconflict_free(alpm_fileconflict_t *conflict); +const alpm_file_t *_alpm_filelist_contains(const alpm_list_t *haystack, + const char *needle); + #endif /* _ALPM_CONFLICT_H */ /* vim: set ts=2 sw=2 noet: */ diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 0319d291..c3681b34 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -269,22 +269,20 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_handle_t *handle, alpm_list_t *pkglis alpm_list_t *remove, alpm_list_t *upgrade, int reversedeps) { alpm_list_t *i, *j; - alpm_list_t *targets, *dblist = NULL, *modified = NULL; + alpm_list_t *dblist = NULL, *modified = NULL; alpm_list_t *baddeps = NULL; int nodepversion; CHECK_HANDLE(handle, return NULL); - targets = alpm_list_join(alpm_list_copy(remove), alpm_list_copy(upgrade)); for(i = pkglist; i; i = i->next) { alpm_pkg_t *pkg = i->data; - if(_alpm_pkg_find(targets, pkg->name)) { + if(_alpm_pkg_find(remove, pkg->name) || _alpm_pkg_find(upgrade, pkg->name)) { modified = alpm_list_add(modified, pkg); } else { dblist = alpm_list_add(dblist, pkg); } } - alpm_list_free(targets); nodepversion = no_dep_version(handle); diff --git a/lib/libalpm/diskspace.c b/lib/libalpm/diskspace.c index 52364a0e..3ab62a86 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -39,10 +39,6 @@ #include <sys/types.h> #endif -/* libarchive */ -#include <archive.h> -#include <archive_entry.h> - /* libalpm */ #include "diskspace.h" #include "alpm_list.h" @@ -151,14 +147,15 @@ static alpm_mountpoint_t *match_mount_point(const alpm_list_t *mount_points, static int calculate_removed_size(alpm_handle_t *handle, const alpm_list_t *mount_points, alpm_pkg_t *pkg) { - alpm_list_t *file; + alpm_list_t *i; alpm_list_t *files = alpm_pkg_get_files(pkg); - for(file = files; file; file = file->next) { + for(i = files; i; i = i->next) { alpm_mountpoint_t *mp; struct stat st; char path[PATH_MAX]; - const char *filename = file->data; + const alpm_file_t *file = i->data; + const char *filename = file->name; snprintf(path, PATH_MAX, "%s%s", handle->root, filename); _alpm_lstat(path, &st); @@ -188,39 +185,19 @@ static int calculate_removed_size(alpm_handle_t *handle, static int calculate_installed_size(alpm_handle_t *handle, const alpm_list_t *mount_points, alpm_pkg_t *pkg) { - int ret=0; - struct archive *archive; - struct archive_entry *entry; - - if((archive = archive_read_new()) == NULL) { - handle->pm_errno = ALPM_ERR_LIBARCHIVE; - ret = -1; - goto cleanup; - } - - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); - - if(archive_read_open_filename(archive, pkg->origin_data.file, - ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) { - handle->pm_errno = ALPM_ERR_PKG_OPEN; - ret = -1; - goto cleanup; - } + alpm_list_t *i; - while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { + for(i = alpm_pkg_get_files(pkg); i; i = i->next) { + const alpm_file_t *file = i->data; alpm_mountpoint_t *mp; - const char *filename; - mode_t mode; char path[PATH_MAX]; - filename = archive_entry_pathname(entry); - mode = archive_entry_mode(entry); + const char *filename = file->name; /* libarchive reports these as zero size anyways */ /* NOTE: if we do start accounting for directory size, a dir matching a * mountpoint needs to be attributed to the parent, not the mountpoint. */ - if(S_ISDIR(mode) || S_ISLNK(mode)) { + if(S_ISDIR(file->mode) || S_ISLNK(file->mode)) { continue; } @@ -240,21 +217,11 @@ static int calculate_installed_size(alpm_handle_t *handle, /* the addition of (divisor - 1) performs ceil() with integer division */ mp->blocks_needed += - (archive_entry_size(entry) + mp->fsp.f_bsize - 1l) / mp->fsp.f_bsize; + (file->size + mp->fsp.f_bsize - 1l) / mp->fsp.f_bsize; mp->used |= USED_INSTALL; - - if(archive_read_data_skip(archive)) { - _alpm_log(handle, ALPM_LOG_ERROR, _("error while reading package %s: %s\n"), - pkg->name, archive_error_string(archive)); - handle->pm_errno = ALPM_ERR_LIBARCHIVE; - break; - } } - archive_read_finish(archive); - -cleanup: - return ret; + return 0; } int _alpm_check_diskspace(alpm_handle_t *handle) diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c index dc8ee395..c7a1c2b2 100644 --- a/lib/libalpm/dload.c +++ b/lib/libalpm/dload.c @@ -211,7 +211,7 @@ static int curl_download_internal(alpm_handle_t *handle, /* a previous partial download exists, resume from end of file. */ open_mode = "ab"; curl_easy_setopt(handle->curl, CURLOPT_RESUME_FROM, (long)st.st_size); - _alpm_log(handle, ALPM_LOG_DEBUG, "tempfile found, attempting continuation"); + _alpm_log(handle, ALPM_LOG_DEBUG, "tempfile found, attempting continuation\n"); dlfile.initial_size = (double)st.st_size; } diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 28fa08cb..ae9b9a9d 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -427,6 +427,33 @@ alpm_list_t SYMEXPORT *alpm_pkg_compute_requiredby(alpm_pkg_t *pkg) /** @} */ +void _alpm_files_free(alpm_file_t *file) +{ + free(file->name); + free(file); +} + +alpm_file_t *_alpm_files_dup(const alpm_file_t *file) +{ + alpm_file_t *newfile; + CALLOC(newfile, 1, sizeof(alpm_file_t), return NULL); + + STRDUP(newfile->name, file->name, return NULL); + newfile->size = file->size; + newfile->mode = file->mode; + + return newfile; +} + +/* Helper function for comparing files list entries + */ +int _alpm_files_cmp(const void *f1, const void *f2) +{ + const alpm_file_t *file1 = f1; + const alpm_file_t *file2 = f2; + return strcmp(file1->name, file2->name); +} + alpm_pkg_t *_alpm_pkg_new(void) { alpm_pkg_t* pkg; @@ -466,7 +493,9 @@ alpm_pkg_t *_alpm_pkg_dup(alpm_pkg_t *pkg) newpkg->licenses = alpm_list_strdup(pkg->licenses); newpkg->replaces = alpm_list_strdup(pkg->replaces); newpkg->groups = alpm_list_strdup(pkg->groups); - newpkg->files = alpm_list_strdup(pkg->files); + for(i = pkg->files; i; i = alpm_list_next(i)) { + newpkg->files = alpm_list_add(newpkg->files, _alpm_files_dup(i->data)); + } for(i = pkg->backup; i; i = alpm_list_next(i)) { newpkg->backup = alpm_list_add(newpkg->backup, _alpm_backup_dup(i->data)); } @@ -516,7 +545,8 @@ void _alpm_pkg_free(alpm_pkg_t *pkg) FREELIST(pkg->licenses); FREELIST(pkg->replaces); FREELIST(pkg->groups); - FREELIST(pkg->files); + alpm_list_free_inner(pkg->files, (alpm_list_fn_free)_alpm_files_free); + alpm_list_free(pkg->files); alpm_list_free_inner(pkg->backup, (alpm_list_fn_free)_alpm_backup_free); alpm_list_free(pkg->backup); alpm_list_free_inner(pkg->depends, (alpm_list_fn_free)_alpm_dep_free); @@ -566,8 +596,8 @@ int _alpm_pkg_compare_versions(alpm_pkg_t *spkg, alpm_pkg_t *localpkg) */ int _alpm_pkg_cmp(const void *p1, const void *p2) { - alpm_pkg_t *pkg1 = (alpm_pkg_t *)p1; - alpm_pkg_t *pkg2 = (alpm_pkg_t *)p2; + const alpm_pkg_t *pkg1 = p1; + const alpm_pkg_t *pkg2 = p2; return strcoll(pkg1->name, pkg2->name); } diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index 772c2f62..b6021939 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -139,6 +139,10 @@ struct __alpm_pkg_t { struct pkg_operations *ops; }; +void _alpm_files_free(alpm_file_t *file); +alpm_file_t *_alpm_files_dup(const alpm_file_t *file); +int _alpm_files_cmp(const void *f1, const void *f2); + alpm_pkg_t* _alpm_pkg_new(void); alpm_pkg_t *_alpm_pkg_dup(alpm_pkg_t *pkg); void _alpm_pkg_free(alpm_pkg_t *pkg); diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 2d6fcf64..59374dcb 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -43,6 +43,7 @@ #include "db.h" #include "deps.h" #include "handle.h" +#include "conflict.h" int SYMEXPORT alpm_remove_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg) { @@ -191,25 +192,25 @@ int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data) return 0; } -static int can_remove_file(alpm_handle_t *handle, const char *path, +static int can_remove_file(alpm_handle_t *handle, const alpm_file_t *file, alpm_list_t *skip_remove) { - char file[PATH_MAX]; + char filepath[PATH_MAX]; - snprintf(file, PATH_MAX, "%s%s", handle->root, path); + snprintf(filepath, PATH_MAX, "%s%s", handle->root, file->name); - if(alpm_list_find_str(skip_remove, file)) { + if(alpm_list_find_str(skip_remove, filepath)) { /* return success because we will never actually remove this file */ return 1; } /* If we fail write permissions due to a read-only filesystem, abort. * Assume all other possible failures are covered somewhere else */ - if(access(file, W_OK) == -1) { - if(errno != EACCES && errno != ETXTBSY && access(file, F_OK) == 0) { + if(access(filepath, W_OK) == -1) { + if(errno != EACCES && errno != ETXTBSY && access(filepath, F_OK) == 0) { /* only return failure if the file ACTUALLY exists and we can't write to * it - ignore "chmod -w" simple permission failures */ _alpm_log(handle, ALPM_LOG_ERROR, _("cannot remove file '%s': %s\n"), - file, strerror(errno)); + filepath, strerror(errno)); return 0; } } @@ -219,18 +220,18 @@ static int can_remove_file(alpm_handle_t *handle, const char *path, /* Helper function for iterating through a package's file and deleting them * Used by _alpm_remove_commit. */ -static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, const char *filename, - alpm_list_t *skip_remove, int nosave) +static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, + const alpm_file_t *fileobj, alpm_list_t *skip_remove, int nosave) { struct stat buf; char file[PATH_MAX]; - snprintf(file, PATH_MAX, "%s%s", handle->root, filename); + snprintf(file, PATH_MAX, "%s%s", handle->root, fileobj->name); /* check the remove skip list before removing the file. * see the big comment block in db_find_fileconflicts() for an * explanation. */ - if(alpm_list_find_str(skip_remove, filename)) { + if(alpm_list_find_str(skip_remove, fileobj->name)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is in skip_remove, skipping removal\n", file); return; @@ -254,7 +255,7 @@ static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, const char *fil } } else { /* if the file needs backup and has been modified, back it up to .pacsave */ - alpm_backup_t *backup = _alpm_needbackup(filename, alpm_pkg_get_backup(info)); + alpm_backup_t *backup = _alpm_needbackup(fileobj->name, alpm_pkg_get_backup(info)); if(backup) { if(nosave) { _alpm_log(handle, ALPM_LOG_DEBUG, "transaction is set to NOSAVE, not backing up '%s'\n", file); @@ -277,7 +278,7 @@ static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, const char *fil if(unlink(file) == -1) { _alpm_log(handle, ALPM_LOG_ERROR, _("cannot remove file '%s': %s\n"), - filename, strerror(errno)); + file, strerror(errno)); } } } @@ -285,8 +286,7 @@ static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, const char *fil int _alpm_upgraderemove_package(alpm_handle_t *handle, alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg) { - alpm_list_t *skip_remove, *b; - alpm_list_t *newfiles, *lp; + alpm_list_t *skip_remove, *b, *lp; size_t filenum = 0; alpm_list_t *files = alpm_pkg_get_files(oldpkg); const char *pkgname = alpm_pkg_get_name(oldpkg); @@ -309,7 +309,7 @@ int _alpm_upgraderemove_package(alpm_handle_t *handle, for(b = alpm_pkg_get_backup(newpkg); b; b = b->next) { const alpm_backup_t *backup = b->data; /* safety check (fix the upgrade026 pactest) */ - if(!alpm_list_find_str(filelist, backup->name)) { + if(!_alpm_filelist_contains(filelist, backup->name)) { continue; } _alpm_log(handle, ALPM_LOG_DEBUG, "adding %s to the skip_remove array\n", @@ -329,11 +329,9 @@ int _alpm_upgraderemove_package(alpm_handle_t *handle, _alpm_log(handle, ALPM_LOG_DEBUG, "removing %ld files\n", (unsigned long)filenum); /* iterate through the list backwards, unlinking files */ - newfiles = alpm_list_reverse(files); - for(lp = newfiles; lp; lp = alpm_list_next(lp)) { + for(lp = alpm_list_last(files); lp; lp = alpm_list_previous(files, lp)) { unlink_file(handle, oldpkg, lp->data, skip_remove, 0); } - alpm_list_free(newfiles); FREELIST(skip_remove); db: @@ -390,7 +388,6 @@ int _alpm_remove_packages(alpm_handle_t *handle) if(!(trans->flags & ALPM_TRANS_FLAG_DBONLY)) { alpm_list_t *files = alpm_pkg_get_files(info); - alpm_list_t *newfiles; size_t filenum = 0; for(lp = files; lp; lp = lp->next) { @@ -409,8 +406,7 @@ int _alpm_remove_packages(alpm_handle_t *handle) pkg_count, (pkg_count - targcount + 1)); /* iterate through the list backwards, unlinking files */ - newfiles = alpm_list_reverse(files); - for(lp = newfiles; lp; lp = alpm_list_next(lp)) { + for(lp = alpm_list_last(files); lp; lp = alpm_list_previous(files, lp)) { int percent; unlink_file(handle, info, lp->data, NULL, trans->flags & ALPM_TRANS_FLAG_NOSAVE); @@ -420,7 +416,6 @@ int _alpm_remove_packages(alpm_handle_t *handle) percent, pkg_count, (pkg_count - targcount + 1)); position++; } - alpm_list_free(newfiles); } /* set progress to 100% after we finish unlinking files */ diff --git a/src/pacman/package.c b/src/pacman/package.c index 1a08c0bb..5514f001 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -218,7 +218,7 @@ void dump_pkg_backups(alpm_pkg_t *pkg) */ void dump_pkg_files(alpm_pkg_t *pkg, int quiet) { - const char *pkgname, *root, *filestr; + const char *pkgname, *root; alpm_list_t *i, *pkgfiles; pkgname = alpm_pkg_get_name(pkg); @@ -226,11 +226,11 @@ void dump_pkg_files(alpm_pkg_t *pkg, int quiet) root = alpm_option_get_root(config->handle); for(i = pkgfiles; i; i = alpm_list_next(i)) { - filestr = alpm_list_getdata(i); + const alpm_file_t *file = alpm_list_getdata(i); if(!quiet){ - fprintf(stdout, "%s %s%s\n", pkgname, root, filestr); + fprintf(stdout, "%s %s%s\n", pkgname, root, file->name); } else { - fprintf(stdout, "%s%s\n", root, filestr); + fprintf(stdout, "%s%s\n", root, file->name); } } diff --git a/src/pacman/query.c b/src/pacman/query.c index df4f7f19..045dc7f0 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -193,7 +193,8 @@ static int query_fileowner(alpm_list_t *targets) for(j = alpm_pkg_get_files(info); j && !found; j = alpm_list_next(j)) { char *ppath, *pdname; - const char *pkgfile = alpm_list_getdata(j); + const alpm_file_t *file = alpm_list_getdata(j); + const char *pkgfile = file->name; /* avoid the costly resolve_path usage if the basenames don't match */ if(strcmp(mbasename(pkgfile), bname) != 0) { @@ -416,7 +417,8 @@ static int check(alpm_pkg_t *pkg) const char *pkgname = alpm_pkg_get_name(pkg); for(i = alpm_pkg_get_files(pkg); i; i = alpm_list_next(i)) { struct stat st; - const char *path = alpm_list_getdata(i); + const alpm_file_t *file = alpm_list_getdata(i); + const char *path = file->name; if(rootlen + 1 + strlen(path) > PATH_MAX) { pm_fprintf(stderr, ALPM_LOG_WARNING, _("path too long: %s%s\n"), root, path); diff --git a/test/pacman/tests/fileconflict001.py b/test/pacman/tests/fileconflict001.py index 8c13911c..dec61512 100644 --- a/test/pacman/tests/fileconflict001.py +++ b/test/pacman/tests/fileconflict001.py @@ -2,6 +2,7 @@ self.description = "Fileconflict with symlinks" lp = pmpkg("dummy") lp.files = ["dir/realdir/", + "dir/realdir/realfile", "dir/symdir -> realdir"] self.addpkg2db("local", lp) @@ -18,5 +19,7 @@ self.args = "-U %s" % " ".join([p.filename() for p in p1, p2]) self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg1") self.addrule("!PKG_EXIST=pkg2") +self.addrule("FILE_EXIST=dir/realdir/realfile") +self.addrule("!FILE_EXIST=dir/realdir/file") self.expectfailure = True diff --git a/test/pacman/tests/fileconflict002.py b/test/pacman/tests/fileconflict002.py index f70873ba..e107cd2e 100644 --- a/test/pacman/tests/fileconflict002.py +++ b/test/pacman/tests/fileconflict002.py @@ -1,12 +1,16 @@ self.description = "Fileconflict with symlinks (2)" p1 = pmpkg("pkg1") -p1.files = ["dir/realdir/file", +p1.files = ["dir/", + "dir/realdir/", + "dir/realdir/file", "dir/symdir -> realdir"] self.addpkg(p1) p2 = pmpkg("pkg2") -p2.files = ["dir/symdir/file"] +p2.files = ["dir/", + "dir/symdir/", + "dir/symdir/file"] self.addpkg(p2) self.args = "-U %s" % " ".join([p.filename() for p in p1, p2]) @@ -14,5 +18,6 @@ self.args = "-U %s" % " ".join([p.filename() for p in p1, p2]) self.addrule("PACMAN_RETCODE=1") self.addrule("!PKG_EXIST=pkg1") self.addrule("!PKG_EXIST=pkg2") +self.addrule("!FILE_EXIST=dir/realdir/file") self.expectfailure = True |