[pacman-dev] [PATCH 4/4] testdb: check local database for duplicate files

Dan McGee dan at archlinux.org
Sat Jan 7 12:28:59 EST 2012


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 at archlinux.org>
---
 src/util/testdb.c |   85 ++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/src/util/testdb.c b/src/util/testdb.c
index 4f6bfed..c12aee0 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);
-- 
1.7.8.1



More information about the pacman-dev mailing list