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 <dan@archlinux.org>
This commit is contained in:
Dan McGee 2011-06-16 13:16:49 -05:00
parent a2995f586e
commit 6a6fc3107f
11 changed files with 133 additions and 51 deletions

View File

@ -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;

View File

@ -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");

View File

@ -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;
}

View File

@ -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,

View File

@ -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: */

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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",

View File

@ -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);
}
}

View File

@ -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);