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); }