[pacman-dev] [PATCH] New feature: files verification

changaco changaco at laposte.net
Sat Mar 28 09:52:59 EDT 2009


>From 7c0348fa499f55968764fef4c7bb3d3d7245932b Mon Sep 17 00:00:00 2001
From: Charly COSTE <changaco at laposte.net>
Date: Sat, 28 Mar 2009 12:36:23 +0100
Subject: [PATCH] New feature: files verification

A new option "-Qy" which checks if the files owned by a/some/all package(s) really are on the system (i.e. not accidentally deleted). http://bugs.archlinux.org/task/13877

Signed-off-by: Charly COSTE <changaco at laposte.net>
---
 src/pacman/conf.h   |    1 +
 src/pacman/pacman.c |    6 +++-
 src/pacman/query.c  |   87 +++++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 84 insertions(+), 10 deletions(-)

diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 466d983..01a1828 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -50,6 +50,7 @@ typedef struct __config_t {
 	unsigned short op_q_search;
 	unsigned short op_q_changelog;
 	unsigned short op_q_upgrade;
+	unsigned short op_q_verify;
 
 	unsigned short op_s_clean;
 	unsigned short op_s_downloadonly;
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 59916d6..e1d13a4 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -360,6 +360,7 @@ static int parseargs(int argc, char *argv[])
 		{"verbose",    no_argument,       0, 'v'},
 		{"downloadonly", no_argument,     0, 'w'},
 		{"refresh",    no_argument,       0, 'y'},
+		{"verify",     no_argument,       0, 'y'},
 		{"noconfirm",  no_argument,       0, 1000},
 		{"config",     required_argument, 0, 1001},
 		{"ignore",     required_argument, 0, 1002},
@@ -510,7 +511,10 @@ static int parseargs(int argc, char *argv[])
 				config->flags |= PM_TRANS_FLAG_DOWNLOADONLY;
 				config->flags |= PM_TRANS_FLAG_NOCONFLICTS;
 				break;
-			case 'y': (config->op_s_sync)++; break;
+			case 'y':
+				(config->op_s_sync)++;
+				config->op_q_verify = 1;
+				break;
 			case '?': return(1);
 			default: return(1);
 		}
diff --git a/src/pacman/query.c b/src/pacman/query.c
index 0d48638..2a7dba5 100644
--- a/src/pacman/query.c
+++ b/src/pacman/query.c
@@ -334,10 +334,70 @@ static void display(pmpkg_t *pkg)
 	}
 }
 
+// We loop through the packages and for each packages we loop through files to check if they exist
+static void verify(alpm_list_t *pkgs)
+{
+	alpm_list_t *i, *files, *file, *pkgs2repair;
+	pmpkg_t *pkg;
+	struct stat stFileInfo;
+	int pkgs_n = alpm_list_count(pkgs);
+	int j = 0, k = 0;
+	for(i = pkgs; i; i = alpm_list_next(i)) {
+		j++;
+		pkg = alpm_list_getdata(i);
+		char *pkgname = alpm_pkg_get_name(pkg);
+		if(filter(pkg)) {
+			files = alpm_pkg_get_files(pkg);
+			for(file = files; file; file = alpm_list_next(file)){
+				char *x = alpm_list_getdata(file);
+				char *f = malloc (strlen(x)+2);
+				strcpy(f,"/");
+				strcat(f, x);
+				k++;
+				if(strncmp(f, "/tmp", 4)==0){
+					continue; // ignore files in /tmp
+				}
+				if(lstat(f,&stFileInfo) == 0) { // we use lstat to prevent errors from symbolic links
+					if(!config->quiet){
+						fprintf(stderr, "\rfile n°%i (package %i/%i): OK", k, j, pkgs_n); fflush(stdout);
+					}
+				}
+				else {
+					if(config->quiet){
+						fprintf(stderr, "%s %s\n", pkgname, f); fflush(stdout);
+					} else {
+						fprintf(stderr, "\rfile n°%i (package %i/%i): Missing file owned by \"%s\": %s\n", k, j, pkgs_n, pkgname, f); fflush(stdout);
+					}
+					if(alpm_list_find_ptr(pkgs2repair, pkgname) == NULL) {
+						pkgs2repair = alpm_list_add(pkgs2repair, pkgname);
+					}
+				}
+			}
+		}
+	}
+	if(!config->quiet){
+		fprintf(stderr, "\n");
+	}
+	if(alpm_list_count(pkgs2repair) > 0) {
+		if(!config->quiet){
+			fprintf(stderr, "Damaged packages: ");
+		}
+		for(i = pkgs2repair; i; i = alpm_list_next(i)) {
+			fprintf(stdout, "%s ", alpm_list_getdata(i));
+		}
+	} else {
+		if(!config->quiet){
+			fprintf(stderr, "No damaged packages.");
+		}
+	}
+	fprintf(stdout, "\n");
+	fflush(stdout);
+}
+
 int pacman_query(alpm_list_t *targets)
 {
 	int ret = 0;
-	alpm_list_t *i;
+	alpm_list_t *i, *pkgs;
 
 	/* First: operations that do not require targets */
 
@@ -363,18 +423,20 @@ int pacman_query(alpm_list_t *targets)
 	}
 
 	/* operations on all packages in the local DB
-	 * valid: no-op (plain -Q), list, info
+	 * valid: no-op (plain -Q), list, info, verify
 	 * invalid: isfile, owns */
 	if(targets == NULL) {
 		if(config->op_q_isfile || config->op_q_owns) {
 			pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n"));
 			return(1);
-		}
-
-		for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) {
-			pmpkg_t *pkg = alpm_list_getdata(i);
-			if(filter(pkg)) {
-				display(pkg);
+		} else if(config->op_q_verify) {
+			verify(alpm_db_get_pkgcache(db_local));
+		} else {
+			for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) {
+				pmpkg_t *pkg = alpm_list_getdata(i);
+				if(filter(pkg)) {
+					display(pkg);
+				}
 			}
 		}
 		return(0);
@@ -389,7 +451,7 @@ int pacman_query(alpm_list_t *targets)
 	}
 
 	/* operations on named packages in the local DB
-	 * valid: no-op (plain -Q), list, info */
+	 * valid: no-op (plain -Q), list, info, verify */
 	for(i = targets; i; i = alpm_list_next(i)) {
 		char *strname = alpm_list_getdata(i);
 		pmpkg_t *pkg = NULL;
@@ -406,8 +468,12 @@ int pacman_query(alpm_list_t *targets)
 			continue;
 		}
 
+		
 		if(filter(pkg)) {
 			display(pkg);
+			if(config->op_q_verify){
+				pkgs = alpm_list_add(pkgs, pkg);
+			}
 		}
 
 		if(config->op_q_isfile) {
@@ -415,6 +481,9 @@ int pacman_query(alpm_list_t *targets)
 			pkg = NULL;
 		}
 	}
+	if(config->op_q_verify){
+		verify(pkgs);
+	}
 
 	return(ret);
 }
-- 
1.6.2.1

 Créez votre adresse électronique prenom.nom at laposte.net 
 1 Go d'espace de stockage, anti-spam et anti-virus intégrés.


More information about the pacman-dev mailing list