From 6a6fc3107f477e579b0dd21553d48e073e3efdf4 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 16 Jun 2011 13:16:49 -0500 Subject: Move alpm filelists to a struct object This allows us to capture size and mode data when building filelists from package files. Future patches will take advantage of this newly available information, and frontends can use it as well. Signed-off-by: Dan McGee --- lib/libalpm/alpm.h | 7 ++++++ lib/libalpm/be_local.c | 13 +++++++----- lib/libalpm/be_package.c | 14 +++++++++--- lib/libalpm/conflict.c | 55 ++++++++++++++++++++++++++++++++++-------------- lib/libalpm/conflict.h | 3 +++ lib/libalpm/diskspace.c | 7 +++--- lib/libalpm/package.c | 38 +++++++++++++++++++++++++++++---- lib/libalpm/package.h | 4 ++++ lib/libalpm/remove.c | 29 +++++++++++++------------ src/pacman/package.c | 8 +++---- src/pacman/query.c | 6 ++++-- 11 files changed, 133 insertions(+), 51 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 76564271..88aef37f 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/be_local.c b/lib/libalpm/be_local.c index 65579673..f1056d40 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -632,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))) { @@ -835,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 a4c6c559..da5076e5 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, PM_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/conflict.c b/lib/libalpm/conflict.c index 5d9bbf23..6ed9981e 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); @@ -415,7 +435,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle, return NULL; } } - FREELIST(common_files); + alpm_list_free(common_files); } } @@ -440,7 +460,9 @@ 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; /* have we acted on this conflict? */ int resolved_conflict = 0; @@ -475,7 +497,8 @@ 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, PM_LOG_DEBUG, "local file will be removed, not a conflict: %s\n", relative_path); @@ -492,7 +515,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_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 */ @@ -509,7 +532,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, PM_LOG_DEBUG, "check if all files in %s belongs to %s\n", dir, dbpkg->name); @@ -526,7 +549,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 +562,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 +570,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, PM_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/diskspace.c b/lib/libalpm/diskspace.c index 7ca72c3c..5fb36eb4 100644 --- a/lib/libalpm/diskspace.c +++ b/lib/libalpm/diskspace.c @@ -151,14 +151,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); diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 21984b37..f69ba0b3 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 48adf045..d967780c 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, PM_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, PM_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, PM_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, PM_LOG_ERROR, _("cannot remove file '%s': %s\n"), - filename, strerror(errno)); + file, strerror(errno)); } } } @@ -308,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, PM_LOG_DEBUG, "adding %s to the skip_remove array\n", diff --git a/src/pacman/package.c b/src/pacman/package.c index 6b480873..c394bf9a 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 826c2262..1547c247 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, PM_LOG_WARNING, _("path too long: %s%s\n"), root, path); -- cgit v1.2.3-70-g09d2