mirror of
https://github.com/moparisthebest/pacman
synced 2024-12-23 00:08:50 -05:00
New feature: files verification
This implements FS#13877. Add a new option "-Qk" which checks if all of the files for a given package (or packages) are really on the system (i.e. not accidentally deleted). This can be combined with filters and other display options. It also respects both the --quiet and --verbose flags to give varying levels of output. Based on the original patch by Charly Coste <changaco@laposte.net>, thanks for your work! Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
parent
4b21504ffc
commit
ca6ef852f9
@ -183,6 +183,7 @@ _pacman ()
|
|||||||
search) mod="${mod}s" ;;
|
search) mod="${mod}s" ;;
|
||||||
upgrades) mod="${mod}u" ;;
|
upgrades) mod="${mod}u" ;;
|
||||||
cascade) mod="${mod}c" ;;
|
cascade) mod="${mod}c" ;;
|
||||||
|
check) mod="${mod}k" ;;
|
||||||
dbonly) mod="${mod}k" ;;
|
dbonly) mod="${mod}k" ;;
|
||||||
nosave) mod="${mod}n" ;;
|
nosave) mod="${mod}n" ;;
|
||||||
recursive) mod="${mod}s" ;;
|
recursive) mod="${mod}s" ;;
|
||||||
@ -294,6 +295,7 @@ _pacman ()
|
|||||||
-g --groups \
|
-g --groups \
|
||||||
-h --help \
|
-h --help \
|
||||||
-i --info \
|
-i --info \
|
||||||
|
-k --check \
|
||||||
-l --list \
|
-l --list \
|
||||||
-m --foreign \
|
-m --foreign \
|
||||||
-o --owns \
|
-o --owns \
|
||||||
|
@ -50,6 +50,7 @@ _pacman_opts_query_modifiers=(
|
|||||||
'-e[List packages explicitly installed]'
|
'-e[List packages explicitly installed]'
|
||||||
'-i[View package information]'
|
'-i[View package information]'
|
||||||
'-ii[View package information including backup files]'
|
'-ii[View package information including backup files]'
|
||||||
|
'-k[Check package files]'
|
||||||
'-l[List package contents]'
|
'-l[List package contents]'
|
||||||
'-m[List installed packages not found in sync db(s)]'
|
'-m[List installed packages not found in sync db(s)]'
|
||||||
'-t[List packages not required by any package]'
|
'-t[List packages not required by any package]'
|
||||||
|
@ -196,6 +196,11 @@ Query Options[[QO]]
|
|||||||
'\--info' or '-i' flags will also display the list of backup files and
|
'\--info' or '-i' flags will also display the list of backup files and
|
||||||
their modification states.
|
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 or filter flags are not provided,
|
||||||
|
check all installed packages.
|
||||||
|
|
||||||
*-l, \--list*::
|
*-l, \--list*::
|
||||||
List all files owned by a given package. Multiple packages can be
|
List all files owned by a given package. Multiple packages can be
|
||||||
specified on the command line.
|
specified on the command line.
|
||||||
@ -220,7 +225,8 @@ Query Options[[QO]]
|
|||||||
names and not version, group, and description information; owns will
|
names and not version, group, and description information; owns will
|
||||||
only show package names instead of "file is owned by pkg" messages; group
|
only show package names instead of "file is owned by pkg" messages; group
|
||||||
will only show package names and omit group names; list will only show
|
will only show package names and omit group names; list will only show
|
||||||
files and omit package names; a bare query will only show package names
|
files and omit package names; check will only show pairs of package names
|
||||||
|
and missing files; a bare query will only show package names
|
||||||
rather than names and versions.
|
rather than names and versions.
|
||||||
|
|
||||||
*-s, \--search* <'regexp'>::
|
*-s, \--search* <'regexp'>::
|
||||||
|
@ -51,6 +51,7 @@ typedef struct __config_t {
|
|||||||
unsigned short op_q_search;
|
unsigned short op_q_search;
|
||||||
unsigned short op_q_changelog;
|
unsigned short op_q_changelog;
|
||||||
unsigned short op_q_upgrade;
|
unsigned short op_q_upgrade;
|
||||||
|
unsigned short op_q_check;
|
||||||
|
|
||||||
unsigned short op_s_clean;
|
unsigned short op_s_clean;
|
||||||
unsigned short op_s_downloadonly;
|
unsigned short op_s_downloadonly;
|
||||||
|
@ -108,6 +108,7 @@ static void usage(int op, const char * const myname)
|
|||||||
printf(_(" -e, --explicit list packages explicitly installed [filter]\n"));
|
printf(_(" -e, --explicit list packages explicitly installed [filter]\n"));
|
||||||
printf(_(" -g, --groups view all members of a package group\n"));
|
printf(_(" -g, --groups view all members of a package group\n"));
|
||||||
printf(_(" -i, --info view package information (-ii for backup files)\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(_(" -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(_(" -m, --foreign list installed packages not found in sync db(s) [filter]\n"));
|
||||||
printf(_(" -o, --owns <file> query the package that owns <file>\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'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"info", no_argument, 0, 'i'},
|
{"info", no_argument, 0, 'i'},
|
||||||
{"dbonly", no_argument, 0, 'k'},
|
{"dbonly", no_argument, 0, 'k'},
|
||||||
|
{"check", no_argument, 0, 'k'},
|
||||||
{"list", no_argument, 0, 'l'},
|
{"list", no_argument, 0, 'l'},
|
||||||
{"foreign", no_argument, 0, 'm'},
|
{"foreign", no_argument, 0, 'm'},
|
||||||
{"nosave", no_argument, 0, 'n'},
|
{"nosave", no_argument, 0, 'n'},
|
||||||
@ -473,7 +475,10 @@ static int parseargs(int argc, char *argv[])
|
|||||||
case 'g': (config->group)++; break;
|
case 'g': (config->group)++; break;
|
||||||
case 'h': config->help = 1; break;
|
case 'h': config->help = 1; break;
|
||||||
case 'i': (config->op_q_info)++; (config->op_s_info)++; 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 'l': config->op_q_list = 1; break;
|
||||||
case 'm': config->op_q_foreign = 1; break;
|
case 'm': config->op_q_foreign = 1; break;
|
||||||
case 'n': config->flags |= PM_TRANS_FLAG_NOSAVE; break;
|
case 'n': config->flags |= PM_TRANS_FLAG_NOSAVE; break;
|
||||||
|
@ -309,8 +309,60 @@ static int filter(pmpkg_t *pkg)
|
|||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display(pmpkg_t *pkg)
|
/* Loop through the packages. For each package,
|
||||||
|
* loop through files to check if they exist. */
|
||||||
|
static int check(pmpkg_t *pkg)
|
||||||
{
|
{
|
||||||
|
alpm_list_t *i;
|
||||||
|
const char *root;
|
||||||
|
int allfiles = 0, errors = 0;
|
||||||
|
size_t rootlen;
|
||||||
|
char f[PATH_MAX];
|
||||||
|
|
||||||
|
root = alpm_option_get_root();
|
||||||
|
rootlen = strlen(root);
|
||||||
|
if(rootlen + 1 > PATH_MAX) {
|
||||||
|
/* we are in trouble here */
|
||||||
|
pm_fprintf(stderr, PM_LOG_ERROR, _("root path too long\n"));
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
strcpy(f, root);
|
||||||
|
|
||||||
|
const char *pkgname = alpm_pkg_get_name(pkg);
|
||||||
|
for(i = alpm_pkg_get_files(pkg); i; i = alpm_list_next(i)) {
|
||||||
|
struct stat st;
|
||||||
|
const char *path = alpm_list_getdata(i);
|
||||||
|
|
||||||
|
if(rootlen + 1 + strlen(path) > PATH_MAX) {
|
||||||
|
pm_fprintf(stderr, PM_LOG_WARNING, _("file path too long\n"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
strcpy(f + rootlen, path);
|
||||||
|
allfiles++;
|
||||||
|
/* use lstat to prevent errors from symlinks */
|
||||||
|
if(lstat(f, &st) != 0) {
|
||||||
|
if(config->quiet) {
|
||||||
|
printf("%s %s\n", pkgname, f);
|
||||||
|
} else {
|
||||||
|
pm_printf(PM_LOG_WARNING, "%s: missing %s (%s)\n",
|
||||||
|
pkgname, f, strerror(errno));
|
||||||
|
}
|
||||||
|
errors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!config->quiet) {
|
||||||
|
printf("%s: %d total, %d missing file(s)\n",
|
||||||
|
pkgname, allfiles, errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(errors != 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int display(pmpkg_t *pkg)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if(config->op_q_info) {
|
if(config->op_q_info) {
|
||||||
if(config->op_q_isfile) {
|
if(config->op_q_isfile) {
|
||||||
/* omit info that isn't applicable for a file package */
|
/* omit info that isn't applicable for a file package */
|
||||||
@ -325,19 +377,25 @@ static void display(pmpkg_t *pkg)
|
|||||||
if(config->op_q_changelog) {
|
if(config->op_q_changelog) {
|
||||||
dump_pkg_changelog(pkg);
|
dump_pkg_changelog(pkg);
|
||||||
}
|
}
|
||||||
if(!config->op_q_info && !config->op_q_list && !config->op_q_changelog) {
|
if(config->op_q_check) {
|
||||||
|
ret = check(pkg);
|
||||||
|
}
|
||||||
|
if(!config->op_q_info && !config->op_q_list
|
||||||
|
&& !config->op_q_changelog && !config->op_q_check) {
|
||||||
if (!config->quiet) {
|
if (!config->quiet) {
|
||||||
printf("%s %s\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg));
|
printf("%s %s\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg));
|
||||||
} else {
|
} else {
|
||||||
printf("%s\n", alpm_pkg_get_name(pkg));
|
printf("%s\n", alpm_pkg_get_name(pkg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pacman_query(alpm_list_t *targets)
|
int pacman_query(alpm_list_t *targets)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
alpm_list_t *i;
|
alpm_list_t *i;
|
||||||
|
pmpkg_t *pkg = NULL;
|
||||||
|
|
||||||
/* First: operations that do not require targets */
|
/* First: operations that do not require targets */
|
||||||
|
|
||||||
@ -358,12 +416,12 @@ int pacman_query(alpm_list_t *targets)
|
|||||||
alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
|
alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
|
||||||
if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) {
|
if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) {
|
||||||
pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n"));
|
pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n"));
|
||||||
return(-1);
|
return(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* operations on all packages in the local DB
|
/* 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 */
|
* invalid: isfile, owns */
|
||||||
if(targets == NULL) {
|
if(targets == NULL) {
|
||||||
if(config->op_q_isfile || config->op_q_owns) {
|
if(config->op_q_isfile || config->op_q_owns) {
|
||||||
@ -372,12 +430,15 @@ int pacman_query(alpm_list_t *targets)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) {
|
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)) {
|
if(filter(pkg)) {
|
||||||
display(pkg);
|
int value = display(pkg);
|
||||||
|
if(value != 0) {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(0);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Second: operations that require target(s) */
|
/* Second: operations that require target(s) */
|
||||||
@ -389,10 +450,9 @@ int pacman_query(alpm_list_t *targets)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* operations on named packages in the local DB
|
/* 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)) {
|
for(i = targets; i; i = alpm_list_next(i)) {
|
||||||
char *strname = alpm_list_getdata(i);
|
char *strname = alpm_list_getdata(i);
|
||||||
pmpkg_t *pkg = NULL;
|
|
||||||
|
|
||||||
if(config->op_q_isfile) {
|
if(config->op_q_isfile) {
|
||||||
alpm_pkg_load(strname, 1, &pkg);
|
alpm_pkg_load(strname, 1, &pkg);
|
||||||
@ -402,12 +462,15 @@ int pacman_query(alpm_list_t *targets)
|
|||||||
|
|
||||||
if(pkg == NULL) {
|
if(pkg == NULL) {
|
||||||
pm_fprintf(stderr, PM_LOG_ERROR, _("package \"%s\" not found\n"), strname);
|
pm_fprintf(stderr, PM_LOG_ERROR, _("package \"%s\" not found\n"), strname);
|
||||||
ret++;
|
ret = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(filter(pkg)) {
|
if(filter(pkg)) {
|
||||||
display(pkg);
|
int value = display(pkg);
|
||||||
|
if(value != 0) {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config->op_q_isfile) {
|
if(config->op_q_isfile) {
|
||||||
|
Loading…
Reference in New Issue
Block a user