If a package has an mtree file, using pacman -Qkk will read that file and use it to perform more in depth package checking. Currently this only checks for file presence. Signed-off-by: Allan McRae <allan@archlinux.org> --- src/pacman/check.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/pacman/check.h | 3 ++- src/pacman/pacman.c | 2 +- src/pacman/query.c | 6 ++++- 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/pacman/check.c b/src/pacman/check.c index 8317f22..ba9036a 100644 --- a/src/pacman/check.c +++ b/src/pacman/check.c @@ -44,7 +44,7 @@ static int check_file_exists(const char *pkgname, const char * filepath, } /* Loop through the files of the package to check if they exist. */ -int check(alpm_pkg_t *pkg) +int check_pkg_fast(alpm_pkg_t *pkg) { const char *root, *pkgname; size_t errors = 0; @@ -87,3 +87,70 @@ int check(alpm_pkg_t *pkg) return (errors != 0 ? 1 : 0); } + +int check_pkg_full(alpm_pkg_t *pkg) +{ + const char *root, *pkgname; + size_t errors = 0; + size_t rootlen; + char filepath[PATH_MAX]; + struct archive *mtree; + struct archive_entry *entry = NULL; + size_t file_count = 0; + + root = alpm_option_get_root(config->handle); + rootlen = strlen(root); + if(rootlen + 1 > PATH_MAX) { + /* we are in trouble here */ + pm_printf(ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, ""); + return 1; + } + strcpy(filepath, root); + + pkgname = alpm_pkg_get_name(pkg); + mtree = alpm_pkg_mtree_open(pkg); + if(mtree == NULL) { + /* TODO: check error to confirm failure due to no mtree file */ + if(!config->quiet) { + printf(_("%s: no mtree file\n"), pkgname); + } + return 0; + } + + while(alpm_pkg_mtree_next(pkg, mtree, &entry) == ARCHIVE_OK) { + struct stat st; + const char *path = archive_entry_pathname(entry); + + /* ignore special files for the moment */ + if(*path == '.') { + continue; + } + + file_count++; + + if(rootlen + 1 + strlen(path) > PATH_MAX) { + pm_printf(ALPM_LOG_WARNING, _("path too long: %s%s\n"), root, path); + continue; + } + strcpy(filepath + rootlen, path); + + if(check_file_exists(pkgname, filepath, &st) == 1) + { + errors++; + continue; + } + + /* TODO: check file properties */ + } + + alpm_pkg_mtree_close(pkg, mtree); + + if(!config->quiet) { + printf(_n("%s: %jd total file, ", "%s: %jd total files, ", + (unsigned long)file_count), pkgname, (intmax_t)file_count); + printf(_n("%jd altered file\n", "%jd altered files\n", + (unsigned long)errors), (intmax_t)errors); + } + + return (errors != 0 ? 1 : 0); +} diff --git a/src/pacman/check.h b/src/pacman/check.h index b107a7f..f71637c 100644 --- a/src/pacman/check.h +++ b/src/pacman/check.h @@ -22,7 +22,8 @@ #include <alpm.h> -int check(alpm_pkg_t *pkg); +int check_pkg_fast(alpm_pkg_t *pkg); +int check_pkg_full(alpm_pkg_t *pkg); #endif /* _PM_CHECK_H */ diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index 73d5be9..d79f2f9 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -459,7 +459,7 @@ static int parsearg_query(int opt) case 'e': config->op_q_explicit = 1; break; case 'g': (config->group)++; break; case 'i': (config->op_q_info)++; break; - case 'k': config->op_q_check = 1; break; + case 'k': (config->op_q_check)++; break; case 'l': config->op_q_list = 1; break; case 'm': config->op_q_foreign = 1; break; case 'o': config->op_q_owns = 1; break; diff --git a/src/pacman/query.c b/src/pacman/query.c index 12c3412..6b3c3e6 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -419,7 +419,11 @@ static int display(alpm_pkg_t *pkg) dump_pkg_changelog(pkg); } if(config->op_q_check) { - ret = check(pkg); + if(config->op_q_check == 1) { + ret = check_pkg_fast(pkg); + } else { + ret = check_pkg_full(pkg); + } } if(!config->op_q_info && !config->op_q_list && !config->op_q_changelog && !config->op_q_check) { -- 1.7.10.1