summaryrefslogtreecommitdiff
path: root/lib/libalpm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm')
-rw-r--r--lib/libalpm/alpm.h7
-rw-r--r--lib/libalpm/be_local.c13
-rw-r--r--lib/libalpm/be_package.c14
-rw-r--r--lib/libalpm/conflict.c55
-rw-r--r--lib/libalpm/conflict.h3
-rw-r--r--lib/libalpm/diskspace.c7
-rw-r--r--lib/libalpm/package.c38
-rw-r--r--lib/libalpm/package.h4
-rw-r--r--lib/libalpm/remove.c29
9 files changed, 125 insertions, 45 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",