[pacman-dev] [PATCH 2/2] New feature: files verification
Xavier Chantry
shiningxc at gmail.com
Sat Jul 18 14:09:26 EDT 2009
From: Charly COSTE <changaco at laposte.net>
A new option "-Qk" which checks if all packages files are really on the
system (i.e. not accidentally deleted).
This implements FS#13877
Signed-off-by: Charly COSTE <changaco at laposte.net>
[Xav : don't ignore tmp, don't repeat package names in quiet output, add
errno message in verbose output]
Signed-off-by: Xavier Chantry <shiningxc at gmail.com>
---
doc/pacman.8.txt | 4 ++
src/pacman/conf.h | 1 +
src/pacman/pacman.c | 7 +++-
src/pacman/query.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 118 insertions(+), 8 deletions(-)
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index af85a15..ccff167 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -196,6 +196,10 @@ Query Options[[QO]]
'\--info' or '-i' flags will also display the list of backup files and
their modification states.
+*-k \--check*::
+ Check that all files owned by the given package(s) are present on the
+ system. If packages are not specified, check all installed packages.
+
*-l, \--list*::
List all files owned by a given package. Multiple packages can be
specified on the command line.
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 39802ca..6523d49 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -51,6 +51,7 @@ typedef struct __config_t {
unsigned short op_q_search;
unsigned short op_q_changelog;
unsigned short op_q_upgrade;
+ unsigned short op_q_check;
unsigned short op_s_clean;
unsigned short op_s_downloadonly;
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 7f86489..48d45ad 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -108,6 +108,7 @@ static void usage(int op, const char * const myname)
printf(_(" -e, --explicit list packages explicitly installed [filter]\n"));
printf(_(" -g, --groups view all members of a package group\n"));
printf(_(" -i, --info view package information (-ii for backup files)\n"));
+ printf(_(" -k, --check check that the files owned by the package(s) are present\n"));
printf(_(" -l, --list list the contents of the queried package\n"));
printf(_(" -m, --foreign list installed packages not found in sync db(s) [filter]\n"));
printf(_(" -o, --owns <file> query the package that owns <file>\n"));
@@ -345,6 +346,7 @@ static int parseargs(int argc, char *argv[])
{"help", no_argument, 0, 'h'},
{"info", no_argument, 0, 'i'},
{"dbonly", no_argument, 0, 'k'},
+ {"check", no_argument, 0, 'k'},
{"list", no_argument, 0, 'l'},
{"foreign", no_argument, 0, 'm'},
{"nosave", no_argument, 0, 'n'},
@@ -473,7 +475,10 @@ static int parseargs(int argc, char *argv[])
case 'g': (config->group)++; break;
case 'h': config->help = 1; break;
case 'i': (config->op_q_info)++; (config->op_s_info)++; break;
- case 'k': config->flags |= PM_TRANS_FLAG_DBONLY; break;
+ case 'k':
+ config->flags |= PM_TRANS_FLAG_DBONLY;
+ config->op_q_check = 1;
+ break;
case 'l': config->op_q_list = 1; break;
case 'm': config->op_q_foreign = 1; break;
case 'n': config->flags |= PM_TRANS_FLAG_NOSAVE; break;
diff --git a/src/pacman/query.c b/src/pacman/query.c
index 4997202..62eca53 100644
--- a/src/pacman/query.c
+++ b/src/pacman/query.c
@@ -334,10 +334,94 @@ static void display(pmpkg_t *pkg)
}
}
+static void check_display_progress(int j, int pkgs_n, const char *pkgname)
+{
+ char message[getcols()];
+ int len = snprintf(message, getcols(), "(%i/%i) %s %s ...", (int)j, (int)pkgs_n, _("checking"), pkgname);
+ fprintf(stderr, "\r%s %*s", message, getcols()-len-1, " ");
+ fflush(stderr);
+}
+
+/* Loop through the packages. For each package,
+ * loop through files to check if they exist. */
+static void check(alpm_list_t *pkgs)
+{
+ alpm_list_t *i, *files, *file, *damaged = NULL;
+ pmpkg_t *pkg;
+ const char *root;
+ int pkgs_n, j = 0, allfiles = 0;
+ size_t rootlen;
+ char f[PATH_MAX];
+
+ pkgs_n = alpm_list_count(pkgs);
+ root = alpm_option_get_root();
+ rootlen = strlen(root);
+ if(rootlen + 1 > PATH_MAX) {
+ /* we are in trouble here */
+ pm_printf(PM_LOG_ERROR, _("root path too long\n"));
+ return;
+ }
+ strcpy(f, root);
+
+ for(i = pkgs; i; i = alpm_list_next(i)) {
+ j++;
+ pkg = alpm_list_getdata(i);
+ const char *pkgname = alpm_pkg_get_name(pkg);
+ files = alpm_pkg_get_files(pkg);
+ if(!config->quiet) {
+ check_display_progress(j, pkgs_n, pkgname);
+ }
+ for(file = files; file; file = alpm_list_next(file)){
+ struct stat st;
+ char *x = alpm_list_getdata(file);
+ if(rootlen + 1 + strlen(x) > PATH_MAX) {
+ pm_printf(PM_LOG_WARNING, _("file path too long\n"));
+ continue;
+ }
+ strcpy(f + rootlen, x);
+ allfiles++;
+ /* use lstat to prevent errors from symlinks */
+ if(lstat(f,&st) != 0) {
+ if(config->quiet) {
+ fprintf(stderr, "%s %s\n", pkgname, f);
+ fflush(stderr);
+ } else {
+ fprintf(stderr, "\r%s: %s (%s)\n", pkgname, f, strerror(errno));
+ check_display_progress(j, pkgs_n, pkgname);
+ fflush(stderr);
+ }
+ if(alpm_list_find_ptr(damaged, pkgname) == NULL) {
+ damaged = alpm_list_add(damaged, (char*)pkgname);
+ }
+ }
+ }
+ }
+ if(!config->quiet) {
+ char message[getcols()];
+ int len = snprintf(message, getcols(), "%s: %i %s (%i %s)",
+ _("Check complete"), allfiles, _("files"), pkgs_n, _("packages"));
+ fprintf(stderr, "\r%s %*s\n", message, getcols()-len-1, " ");
+ fflush(stderr);
+
+ if(alpm_list_count(damaged) > 0) {
+ fprintf(stderr, "\r%s ", _("Damaged packages:"));
+ fflush(stderr);
+ for(i = damaged; i; i = alpm_list_next(i)) {
+ fprintf(stdout, "%s ", (char*)alpm_list_getdata(i));
+ }
+ fprintf(stdout, "\n");
+ fflush(stdout);
+ }
+ }
+
+ alpm_list_free(damaged);
+}
+
int pacman_query(alpm_list_t *targets)
{
int ret = 0;
- alpm_list_t *i;
+ alpm_list_t *i, *pkgs = NULL;
+ pmpkg_t *pkg = NULL;
/* First: operations that do not require targets */
@@ -363,7 +447,7 @@ 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, check
* invalid: isfile, owns */
if(targets == NULL) {
if(config->op_q_isfile || config->op_q_owns) {
@@ -372,11 +456,19 @@ int pacman_query(alpm_list_t *targets)
}
for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) {
- pmpkg_t *pkg = alpm_list_getdata(i);
+ pkg = alpm_list_getdata(i);
if(filter(pkg)) {
- display(pkg);
+ if(config->op_q_check) {
+ pkgs = alpm_list_add(pkgs, pkg);
+ } else {
+ display(pkg);
+ }
}
}
+ if(config->op_q_check){
+ check(pkgs);
+ alpm_list_free(pkgs);
+ }
return(0);
}
@@ -389,10 +481,9 @@ 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, check */
for(i = targets; i; i = alpm_list_next(i)) {
char *strname = alpm_list_getdata(i);
- pmpkg_t *pkg = NULL;
if(config->op_q_isfile) {
alpm_pkg_load(strname, 1, &pkg);
@@ -406,8 +497,13 @@ int pacman_query(alpm_list_t *targets)
continue;
}
+
if(filter(pkg)) {
- display(pkg);
+ if(config->op_q_check) {
+ pkgs = alpm_list_add(pkgs, pkg);
+ } else {
+ display(pkg);
+ }
}
if(config->op_q_isfile) {
@@ -415,6 +511,10 @@ int pacman_query(alpm_list_t *targets)
pkg = NULL;
}
}
+ if(config->op_q_check){
+ check(pkgs);
+ alpm_list_free(pkgs);
+ }
return(ret);
}
--
1.6.3.3
More information about the pacman-dev
mailing list