summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libalpm/Makefile.am1
-rw-r--r--lib/libalpm/alpm.h16
-rw-r--r--lib/libalpm/be_local.c1
-rw-r--r--lib/libalpm/be_package.c1
-rw-r--r--lib/libalpm/conflict.c97
-rw-r--r--lib/libalpm/conflict.h3
-rw-r--r--lib/libalpm/filelist.c109
-rw-r--r--lib/libalpm/filelist.h36
-rw-r--r--lib/libalpm/package.c9
-rw-r--r--lib/libalpm/package.h1
-rw-r--r--lib/libalpm/remove.c8
11 files changed, 178 insertions, 104 deletions
diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am
index ef448417..911e52bf 100644
--- a/lib/libalpm/Makefile.am
+++ b/lib/libalpm/Makefile.am
@@ -41,6 +41,7 @@ libalpm_la_SOURCES = \
diskspace.h diskspace.c \
dload.h dload.c \
error.c \
+ filelist.h filelist.c \
graph.h graph.c \
group.h group.c \
handle.h handle.c \
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index dd01a416..1d6a8c6c 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -871,7 +871,7 @@ alpm_filelist_t *alpm_pkg_get_files(alpm_pkg_t *pkg);
* "<filename>\t<md5sum>", where the given md5sum is that of
* the file as provided by the package.
* @param pkg a pointer to package
- * @return a reference to an internal list of strings.
+ * @return a reference to a list of alpm_backup_t objects
*/
alpm_list_t *alpm_pkg_get_backup(alpm_pkg_t *pkg);
@@ -950,6 +950,20 @@ int alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason);
/** @} */
/*
+ * Filelists
+ */
+
+/** Determines whether a package filelist contains a given path.
+ * The provided path should be relative to the install root with no leading
+ * slashes, e.g. "etc/localtime". When searching for directories, the path must
+ * have a trailing slash.
+ * @param filelist a pointer to a package filelist
+ * @param path the path to search for in the package
+ * @return a pointer to the matching file or NULL if not found
+ */
+alpm_file_t *alpm_filelist_contains(alpm_filelist_t *filelist, const char *path);
+
+/*
* Signatures
*/
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index a8c8468b..bbc0a8ac 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -37,6 +37,7 @@
#include "handle.h"
#include "package.h"
#include "deps.h"
+#include "filelist.h"
static int local_db_read(alpm_pkg_t *info, alpm_dbinfrq_t inforeq);
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index 07c75a16..8c5b2d16 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -37,6 +37,7 @@
#include "handle.h"
#include "package.h"
#include "deps.h"
+#include "filelist.h"
struct package_changelog {
struct archive *archive;
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index 60691c94..dd153fed 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -38,6 +38,7 @@
#include "util.h"
#include "log.h"
#include "deps.h"
+#include "filelist.h"
static alpm_conflict_t *conflict_new(alpm_pkg_t *pkg1, alpm_pkg_t *pkg2,
alpm_depend_t *reason)
@@ -213,67 +214,6 @@ alpm_list_t SYMEXPORT *alpm_checkconflicts(alpm_handle_t *handle,
return _alpm_innerconflicts(handle, pkglist);
}
-static const int DIFFERENCE = 0;
-static const int INTERSECT = 1;
-/* Returns a set operation on the provided two lists of files.
- * Pre-condition: both lists are sorted!
- * When done, free the list but NOT the contained data.
- *
- * Operations:
- * DIFFERENCE - a difference operation is performed. filesA - filesB.
- * INTERSECT - an intersection operation is performed. filesA & filesB.
- */
-static alpm_list_t *filelist_operation(alpm_filelist_t *filesA,
- alpm_filelist_t *filesB, int operation)
-{
- alpm_list_t *ret = NULL;
- size_t ctrA = 0, ctrB = 0;
-
- while(ctrA < filesA->count && ctrB < filesB->count) {
- alpm_file_t *fileA = filesA->files + ctrA;
- alpm_file_t *fileB = filesB->files + ctrB;
- const char *strA = fileA->name;
- const char *strB = fileB->name;
- /* skip directories, we don't care about them */
- if(strA[strlen(strA)-1] == '/') {
- ctrA++;
- } else if(strB[strlen(strB)-1] == '/') {
- ctrB++;
- } else {
- int cmp = strcmp(strA, strB);
- if(cmp < 0) {
- if(operation == DIFFERENCE) {
- /* item only in filesA, qualifies as a difference */
- ret = alpm_list_add(ret, fileA);
- }
- ctrA++;
- } else if(cmp > 0) {
- ctrB++;
- } else {
- if(operation == INTERSECT) {
- /* item in both, qualifies as an intersect */
- ret = alpm_list_add(ret, fileA);
- }
- ctrA++;
- ctrB++;
- }
- }
- }
-
- /* if doing a difference, ensure we have completely emptied pA */
- while(operation == DIFFERENCE && ctrA < filesA->count) {
- alpm_file_t *fileA = filesA->files + ctrA;
- const char *strA = fileA->name;
- /* skip directories */
- if(strA[strlen(strA)-1] != '/') {
- ret = alpm_list_add(ret, fileA);
- }
- ctrA++;
- }
-
- return ret;
-}
-
/* Adds alpm_fileconflict_t to a conflicts list. Pass the conflicts list, the
* conflicting file path, and either two packages or one package and NULL.
*/
@@ -312,21 +252,6 @@ void _alpm_fileconflict_free(alpm_fileconflict_t *conflict)
FREE(conflict);
}
-const alpm_file_t *_alpm_filelist_contains(alpm_filelist_t *filelist,
- const char *name)
-{
- alpm_file_t key;
-
- if(!filelist) {
- return NULL;
- }
-
- key.name = (char *)name;
-
- return bsearch(&key, filelist->files, filelist->count,
- sizeof(alpm_file_t), _alpm_files_cmp);
-}
-
static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
alpm_pkg_t *pkg)
{
@@ -339,7 +264,7 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
const char *root = handle->root;
/* check directory is actually in package - used for subdirectory checks */
- if(!_alpm_filelist_contains(alpm_pkg_get_files(pkg), dirpath)) {
+ if(!alpm_filelist_contains(alpm_pkg_get_files(pkg), dirpath)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"directory %s not in package %s\n", dirpath, pkg->name);
return 0;
@@ -357,7 +282,7 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
continue;
}
- if(_alpm_filelist_contains(alpm_pkg_get_files(i->data), dirpath)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(i->data), dirpath)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"file %s also in package %s\n", dirpath,
((alpm_pkg_t*)i->data)->name);
@@ -391,7 +316,7 @@ static int dir_belongsto_pkg(alpm_handle_t *handle, const char *dirpath,
return 0;
}
} else {
- if(_alpm_filelist_contains(alpm_pkg_get_files(pkg), path)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(pkg), path)) {
continue;
} else {
closedir(dir);
@@ -442,7 +367,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
for(j = i->next; j; j = j->next) {
alpm_list_t *common_files;
alpm_pkg_t *p2 = j->data;
- common_files = filelist_operation(alpm_pkg_get_files(p1),
+ common_files = _alpm_filelist_operation(alpm_pkg_get_files(p1),
alpm_pkg_get_files(p2), INTERSECT);
if(common_files) {
@@ -475,7 +400,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
if(dbpkg) {
alpm_list_t *difference;
/* older ver of package currently installed */
- difference = filelist_operation(alpm_pkg_get_files(p1),
+ difference = _alpm_filelist_operation(alpm_pkg_get_files(p1),
alpm_pkg_get_files(dbpkg), DIFFERENCE);
tmpfiles.count = alpm_list_count(difference);
tmpfiles.files = alpm_list_to_array(difference, tmpfiles.count,
@@ -529,7 +454,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
/* Check remove list (will we remove the conflicting local file?) */
for(k = rem; k && !resolved_conflict; k = k->next) {
alpm_pkg_t *rempkg = k->data;
- if(rempkg && _alpm_filelist_contains(alpm_pkg_get_files(rempkg),
+ 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\n");
@@ -546,7 +471,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_filelist_contains(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 */
@@ -562,7 +487,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_filelist_contains(alpm_pkg_get_files(dbpkg), dir)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(dbpkg), dir)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"checking if all files in %s belong to %s\n",
dir, dbpkg->name);
@@ -579,7 +504,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
char rpath[PATH_MAX];
if(realpath(path, rpath)) {
const char *relative_rpath = rpath + rootlen;
- if(_alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(dbpkg), relative_rpath)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"package contained the resolved realpath\n");
resolved_conflict = 1;
@@ -592,7 +517,7 @@ alpm_list_t *_alpm_db_find_fileconflicts(alpm_handle_t *handle,
alpm_list_t *local_pkgs = _alpm_db_get_pkgcache(handle->db_local);
int found = 0;
for(k = local_pkgs; k && !found; k = k->next) {
- if(_alpm_filelist_contains(alpm_pkg_get_files(k->data), filestr)) {
+ if(alpm_filelist_contains(alpm_pkg_get_files(k->data), filestr)) {
found = 1;
}
}
diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h
index a129d8b0..0bfdfd76 100644
--- a/lib/libalpm/conflict.h
+++ b/lib/libalpm/conflict.h
@@ -33,9 +33,6 @@ 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(alpm_filelist_t *filelist,
- const char *name);
-
#endif /* _ALPM_CONFLICT_H */
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/filelist.c b/lib/libalpm/filelist.c
new file mode 100644
index 00000000..04075a52
--- /dev/null
+++ b/lib/libalpm/filelist.c
@@ -0,0 +1,109 @@
+/*
+ * filelist.c
+ *
+ * Copyright (c) 2012 Pacman Development Team <pacman-dev@archlinux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+
+/* libalpm */
+#include "filelist.h"
+
+/* Returns a set operation on the provided two lists of files.
+ * Pre-condition: both lists are sorted!
+ * When done, free the list but NOT the contained data.
+ *
+ * Operations:
+ * DIFFERENCE - a difference operation is performed. filesA - filesB.
+ * INTERSECT - an intersection operation is performed. filesA & filesB.
+ */
+alpm_list_t *_alpm_filelist_operation(alpm_filelist_t *filesA,
+ alpm_filelist_t *filesB, enum filelist_op operation)
+{
+ alpm_list_t *ret = NULL;
+ size_t ctrA = 0, ctrB = 0;
+
+ while(ctrA < filesA->count && ctrB < filesB->count) {
+ alpm_file_t *fileA = filesA->files + ctrA;
+ alpm_file_t *fileB = filesB->files + ctrB;
+ const char *strA = fileA->name;
+ const char *strB = fileB->name;
+ /* skip directories, we don't care about them */
+ if(strA[strlen(strA)-1] == '/') {
+ ctrA++;
+ } else if(strB[strlen(strB)-1] == '/') {
+ ctrB++;
+ } else {
+ int cmp = strcmp(strA, strB);
+ if(cmp < 0) {
+ if(operation == DIFFERENCE) {
+ /* item only in filesA, qualifies as a difference */
+ ret = alpm_list_add(ret, fileA);
+ }
+ ctrA++;
+ } else if(cmp > 0) {
+ ctrB++;
+ } else {
+ if(operation == INTERSECT) {
+ /* item in both, qualifies as an intersect */
+ ret = alpm_list_add(ret, fileA);
+ }
+ ctrA++;
+ ctrB++;
+ }
+ }
+ }
+
+ /* if doing a difference, ensure we have completely emptied pA */
+ while(operation == DIFFERENCE && ctrA < filesA->count) {
+ alpm_file_t *fileA = filesA->files + ctrA;
+ const char *strA = fileA->name;
+ /* skip directories */
+ if(strA[strlen(strA)-1] != '/') {
+ ret = alpm_list_add(ret, fileA);
+ }
+ ctrA++;
+ }
+
+ return ret;
+}
+
+/* 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_file_t *alpm_filelist_contains(alpm_filelist_t *filelist,
+ const char *path)
+{
+ alpm_file_t key;
+
+ if(!filelist) {
+ return NULL;
+ }
+
+ key.name = (char *)path;
+
+ return bsearch(&key, filelist->files, filelist->count,
+ sizeof(alpm_file_t), _alpm_files_cmp);
+}
+
+/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/filelist.h b/lib/libalpm/filelist.h
new file mode 100644
index 00000000..991045e9
--- /dev/null
+++ b/lib/libalpm/filelist.h
@@ -0,0 +1,36 @@
+/*
+ * filelist.h
+ *
+ * Copyright (c) 2012 Pacman Development Team <pacman-dev@archlinux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _ALPM_FILELIST_H
+#define _ALPM_FILELIST_H
+
+#include "alpm.h"
+
+enum filelist_op {
+ DIFFERENCE = 0,
+ INTERSECT = 1
+};
+
+alpm_list_t *_alpm_filelist_operation(alpm_filelist_t *filesA,
+ alpm_filelist_t *filesB, enum filelist_op operation);
+
+int _alpm_files_cmp(const void *f1, const void *f2);
+
+#endif /* _ALPM_FILELIST_H */
+
+/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
index 46d14731..a4c3309e 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -450,15 +450,6 @@ alpm_file_t *_alpm_file_copy(alpm_file_t *dest,
return dest;
}
-/* 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;
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index c473549a..313fe9dd 100644
--- a/lib/libalpm/package.h
+++ b/lib/libalpm/package.h
@@ -126,7 +126,6 @@ struct __alpm_pkg_t {
};
alpm_file_t *_alpm_file_copy(alpm_file_t *dest, const alpm_file_t *src);
-int _alpm_files_cmp(const void *f1, const void *f2);
alpm_pkg_t *_alpm_pkg_new(void);
int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr);
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index 148cb863..4c549926 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -41,7 +41,7 @@
#include "db.h"
#include "deps.h"
#include "handle.h"
-#include "conflict.h"
+#include "filelist.h"
/**
* @brief Add a package removal action to the transaction.
@@ -323,7 +323,7 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *oldpkg,
} else if(files < 0) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"keeping directory %s (could not count files)\n", file);
- } else if(newpkg && _alpm_filelist_contains(alpm_pkg_get_files(newpkg),
+ } else if(newpkg && alpm_filelist_contains(alpm_pkg_get_files(newpkg),
fileobj->name)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"keeping directory %s (in new package)\n", file);
@@ -343,7 +343,7 @@ static int unlink_file(alpm_handle_t *handle, alpm_pkg_t *oldpkg,
continue;
}
filelist = alpm_pkg_get_files(local_pkg);
- if(_alpm_filelist_contains(filelist, fileobj->name)) {
+ if(alpm_filelist_contains(filelist, fileobj->name)) {
_alpm_log(handle, ALPM_LOG_DEBUG,
"keeping directory %s (owned by %s)\n", file, local_pkg->name);
found = 1;
@@ -440,7 +440,7 @@ static int remove_package_files(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_filelist_contains(newfiles, backup->name)) {
+ if(!alpm_filelist_contains(newfiles, backup->name)) {
continue;
}
_alpm_log(handle, ALPM_LOG_DEBUG, "adding %s to the skip_remove array\n",