summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2012-01-07 11:26:22 -0600
committerDan McGee <dan@archlinux.org>2012-01-07 11:28:37 -0600
commit6f9ab22fd8c446eab58f1a6bbef7cb984575ef8a (patch)
treeb659cb2e3e5f5fbc91b965f853f1440abdae0530
parent2d794cc031b634c55c77ec17b2b7864f7150ab34 (diff)
downloadpacman-6f9ab22fd8c446eab58f1a6bbef7cb984575ef8a.tar.xz
testdb: check local database for duplicate files
This adds an additional check step to find files in the local database that claim to be owned by more than one package at once, which is definitely not a supported setup. Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--src/util/testdb.c85
1 files changed, 78 insertions, 7 deletions
diff --git a/src/util/testdb.c b/src/util/testdb.c
index 4f6bfed5..c12aee04 100644
--- a/src/util/testdb.c
+++ b/src/util/testdb.c
@@ -92,7 +92,7 @@ static int check_localdb_files(void)
return ret;
}
-static int checkdeps(alpm_list_t *pkglist)
+static int check_deps(alpm_list_t *pkglist)
{
alpm_list_t *data, *i;
int ret = 0;
@@ -101,8 +101,7 @@ static int checkdeps(alpm_list_t *pkglist)
for(i = data; i; i = alpm_list_next(i)) {
alpm_depmissing_t *miss = i->data;
char *depstring = alpm_dep_compute_string(miss->depend);
- printf("missing dependency for %s : %s\n", miss->target,
- depstring);
+ printf("missing %s dependency for %s\n", depstring, miss->target);
free(depstring);
ret++;
}
@@ -110,7 +109,7 @@ static int checkdeps(alpm_list_t *pkglist)
return ret;
}
-static int checkconflicts(alpm_list_t *pkglist)
+static int check_conflicts(alpm_list_t *pkglist)
{
alpm_list_t *data, *i;
int ret = 0;
@@ -126,6 +125,77 @@ static int checkconflicts(alpm_list_t *pkglist)
return ret;
}
+struct fileitem {
+ alpm_file_t *file;
+ alpm_pkg_t *pkg;
+};
+
+static int fileitem_cmp(const void *p1, const void *p2)
+{
+ const struct fileitem * fi1 = p1;
+ const struct fileitem * fi2 = p2;
+ return strcmp(fi1->file->name, fi2->file->name);
+}
+
+static int check_filelists(alpm_list_t *pkglist)
+{
+ alpm_list_t *i;
+ int ret = 0;
+ size_t list_size = 4096;
+ size_t offset = 0, j;
+ struct fileitem *all_files;
+ struct fileitem *prev_fileitem = NULL;
+
+ all_files = malloc(list_size * sizeof(struct fileitem));
+
+ for(i = pkglist; i; i = i->next) {
+ alpm_pkg_t *pkg = i->data;
+ alpm_filelist_t *filelist = alpm_pkg_get_files(pkg);
+ for(j = 0; j < filelist->count; j++) {
+ alpm_file_t *file = filelist->files + j;
+ /* only add files, not directories, to our big list */
+ if(file->name[strlen(file->name) - 1] == '/') {
+ continue;
+ }
+
+ /* do we need to reallocate and grow our array? */
+ if(offset >= list_size) {
+ struct fileitem *new_files;
+ new_files = realloc(all_files, list_size * 2 * sizeof(struct fileitem));
+ if(!new_files) {
+ free(all_files);
+ return 1;
+ }
+ all_files = new_files;
+ list_size *= 2;
+ }
+
+ /* we can finally add it to the list */
+ all_files[offset].file = file;
+ all_files[offset].pkg = pkg;
+ offset++;
+ }
+ }
+
+ /* now sort the list so we can find duplicates */
+ qsort(all_files, offset, sizeof(struct fileitem), fileitem_cmp);
+
+ /* do a 'uniq' style check on the list */
+ for(j = 0; j < offset; j++) {
+ struct fileitem *fileitem = all_files + j;
+ if(prev_fileitem && fileitem_cmp(prev_fileitem, fileitem) == 0) {
+ printf("file owned by %s and %s: %s\n",
+ alpm_pkg_get_name(prev_fileitem->pkg),
+ alpm_pkg_get_name(fileitem->pkg),
+ fileitem->file->name);
+ }
+ prev_fileitem = fileitem;
+ }
+
+ free(all_files);
+ return ret;
+}
+
static int check_localdb(void)
{
int ret = 0;
@@ -139,8 +209,9 @@ static int check_localdb(void)
db = alpm_option_get_localdb(handle);
pkglist = alpm_db_get_pkgcache(db);
- ret += checkdeps(pkglist);
- ret += checkconflicts(pkglist);
+ ret += check_deps(pkglist);
+ ret += check_conflicts(pkglist);
+ ret += check_filelists(pkglist);
return ret;
}
@@ -163,7 +234,7 @@ static int check_syncdbs(alpm_list_t *dbnames)
pkglist = alpm_db_get_pkgcache(db);
syncpkglist = alpm_list_join(syncpkglist, alpm_list_copy(pkglist));
}
- ret += checkdeps(syncpkglist);
+ ret += check_deps(syncpkglist);
cleanup:
alpm_list_free(syncpkglist);