From 72d3713cc7865af5f4d91410ad56ed4287be6109 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 12 Jul 2012 15:29:59 -0500 Subject: Move filelist functions into separate source file We have a few of these and might as well gather them together. This also cleans up the code a bit by using an enum instead of integer values, as well as makes a "search for file in filelist" function public so frontends can do better than straight linear search of the filelists. Signed-off-by: Dan McGee --- lib/libalpm/Makefile.am | 1 + lib/libalpm/alpm.h | 16 ++++++- lib/libalpm/be_local.c | 1 + lib/libalpm/be_package.c | 1 + lib/libalpm/conflict.c | 97 +++++------------------------------------ lib/libalpm/conflict.h | 3 -- lib/libalpm/filelist.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++ lib/libalpm/filelist.h | 36 ++++++++++++++++ lib/libalpm/package.c | 9 ---- lib/libalpm/package.h | 1 - lib/libalpm/remove.c | 8 ++-- 11 files changed, 178 insertions(+), 104 deletions(-) create mode 100644 lib/libalpm/filelist.c create mode 100644 lib/libalpm/filelist.h 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); * "\t", 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); @@ -949,6 +949,20 @@ int alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason); /* End of alpm_pkg */ /** @} */ +/* + * 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 + * + * 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 . + */ + +#include + +/* 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 + * + * 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 . + */ +#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", -- cgit v1.2.3-24-g4f1b