* [gentoo-commits] proj/portage-utils:master commit in: tests/qcheck/, /
@ 2022-04-09 11:32 Fabian Groffen
0 siblings, 0 replies; only message in thread
From: Fabian Groffen @ 2022-04-09 11:32 UTC (permalink / raw
To: gentoo-commits
commit: ede72d3cf08df8ffe7e59c4819d9a6c84ab1659f
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sat Apr 9 11:17:39 2022 +0000
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sat Apr 9 11:32:30 2022 +0000
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=ede72d3c
qcheck: fix config-protect check, bug #837188
ensure we break out of the config-protect directories loop, instead of
just skipping one directory, such that we don't produce bogus amounts of
files, and also don't check despite we were told not to check (-P)
Bug: https://bugs.gentoo.org/837188
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
qcheck.c | 253 ++++++++++++++++++++++++++++-------------------
tests/qcheck/list05.good | 2 +-
tests/qcheck/list07.good | 2 +-
3 files changed, 156 insertions(+), 101 deletions(-)
diff --git a/qcheck.c b/qcheck.c
index 9d9a86c..813c1f7 100644
--- a/qcheck.c
+++ b/qcheck.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2020 Gentoo Foundation
+ * Copyright 2005-2022 Gentoo Foundation
* Distributed under the terms of the GNU General Public License v2
*
* Copyright 2005-2010 Ned Ludd - <solar@gentoo.org>
@@ -74,30 +74,30 @@ static int
qcheck_cb(tree_pkg_ctx *pkg_ctx, void *priv)
{
struct qcheck_opt_state *state = priv;
- FILE *fp_contents_update;
- size_t num_files;
- size_t num_files_ok;
- size_t num_files_unknown;
- size_t num_files_ignored;
- struct stat st;
- char *buffer;
- char *line;
- char *savep;
- int cp_argc;
- int cpm_argc;
- char **cp_argv;
- char **cpm_argv;
- depend_atom *atom;
-
- fp_contents_update = NULL;
-
- /* Open contents */
+ struct stat st;
+ depend_atom *atom;
+ FILE *fp_contents_update = NULL;
+ size_t num_files = 0;
+ size_t num_files_ok = 0;
+ size_t num_files_unknown = 0;
+ size_t num_files_ignored = 0;
+ char *buffer;
+ char *line;
+ char *savep;
+ char *eprefix = NULL;
+ size_t eprefix_len = 0;
+ int cp_argc;
+ int cpm_argc;
+ char **cp_argv;
+ char **cpm_argv;
+
+ /* get CONTENTS from meta */
line = tree_pkg_meta_get(pkg_ctx, CONTENTS);
if (line == NULL)
return EXIT_FAILURE;
atom = tree_get_atom(pkg_ctx, false);
- num_files = num_files_ok = num_files_unknown = num_files_ignored = 0;
+
qcprintf("%sing %s ...\n",
(state->qc_update ? "Updat" : "Check"),
atom_format(state->fmt, atom));
@@ -124,6 +124,10 @@ qcheck_cb(tree_pkg_ctx *pkg_ctx, void *priv)
if (!state->chk_config_protect) {
makeargv(config_protect, &cp_argc, &cp_argv);
makeargv(config_protect_mask, &cpm_argc, &cpm_argv);
+
+ eprefix = tree_pkg_meta_get(pkg_ctx, EPREFIX);
+ if (eprefix != NULL)
+ eprefix_len = strlen(eprefix);
}
buffer = NULL;
@@ -136,8 +140,9 @@ qcheck_cb(tree_pkg_ctx *pkg_ctx, void *priv)
if (!entry)
continue;
- /* run initial checks */
- ++num_files;
+ num_files++;
+
+ /* handle skips */
if (array_cnt(state->regex_arr)) {
size_t n;
regex_t *regex;
@@ -145,15 +150,55 @@ qcheck_cb(tree_pkg_ctx *pkg_ctx, void *priv)
if (!regexec(regex, entry->name, 0, NULL, 0))
break;
if (n < array_cnt(state->regex_arr)) {
- --num_files;
- ++num_files_ignored;
+ num_files--;
+ num_files_ignored++;
+ if (verbose)
+ qcprintf(" %sSKIP%s %s: matches regex\n",
+ YELLOW, NORM, entry->name);
+ if (state->qc_update)
+ fprintf(fp_contents_update, "%s\n", buffer);
continue;
}
}
+
+ /* handle CONFIG_PROTECT-ed files */
+ if (!state->chk_config_protect) {
+ int i;
+ char *p;
+
+ /* compute path without EPREFIX */
+ p = entry->name;
+ if (strlen(p) > eprefix_len)
+ p += eprefix_len;
+
+ /* if in CONFIG_PROTECT_MASK, handle like normal */
+ for (i = 1; i < cpm_argc; ++i) {
+ if (strncmp(cpm_argv[i], p, strlen(cpm_argv[i])) == 0)
+ break;
+ }
+ if (i == cpm_argc) {
+ /* not explicitly unmasked, check if it's protected */
+ for (i = 1; i < cp_argc; ++i) {
+ if (strncmp(cp_argv[i], p, strlen(cp_argv[i])) == 0) {
+ num_files--;
+ num_files_ignored++;
+ if (verbose)
+ qcprintf(" %sSKIP%s %s: protected via %s\n",
+ YELLOW, NORM, entry->name, cp_argv[i]);
+ if (state->qc_update)
+ fprintf(fp_contents_update, "%s\n", buffer);
+ break;
+ }
+ }
+ if (i != cp_argc)
+ continue;
+ }
+ }
+
+ /* check file existence */
if (fstatat(pkg_ctx->cat_ctx->ctx->portroot_fd, entry->name + 1,
- &st, AT_SYMLINK_NOFOLLOW))
+ &st, AT_SYMLINK_NOFOLLOW) != 0)
{
- /* make sure file exists */
if (state->chk_afk) {
if (errno == ENOENT)
qcprintf(" %sAFK%s: %s\n", RED, NORM, entry->name);
@@ -161,42 +206,27 @@ qcheck_cb(tree_pkg_ctx *pkg_ctx, void *priv)
qcprintf(" %sERROR (%s)%s: %s\n", RED,
strerror(errno), NORM, entry->name);
} else {
- --num_files;
- ++num_files_ignored;
+ num_files--;
+ num_files_ignored++;
+ if (verbose)
+ qcprintf(" %sSKIP%s %s: %s\n",
+ YELLOW, NORM, entry->name, strerror(errno));
if (state->qc_update)
fprintf(fp_contents_update, "%s\n", buffer);
}
continue;
}
- /* Handle CONFIG_PROTECT-ed files */
- if (!state->chk_config_protect) {
- int i;
- /* If in CONFIG_PROTECT_MASK, handle like normal */
- for (i = 1; i < cpm_argc; ++i)
- if (strncmp(cpm_argv[i], entry->name, strlen(cpm_argv[i])) == 0)
- break;
- if (i == cpm_argc) {
- /* Not explicitly masked, so it's protected */
- for (i = 1; i < cp_argc; ++i) {
- if (strncmp(cp_argv[i], entry->name,
- strlen(cp_argv[i])) == 0)
- {
- num_files_ok++;
- continue;
- }
- }
- }
- }
-
- /* For certain combinations of flags and filetypes, a file
+ /* for certain combinations of flags and filetypes, a file
* won't get checks and should be ignored */
if (!state->chk_mtime && entry->type == CONTENTS_SYM) {
- --num_files;
- ++num_files_ignored;
+ num_files--;
+ num_files_ignored++;
+ if (verbose)
+ qcprintf(" %sSKIP%s %s: symlink and no mtime check\n",
+ YELLOW, NORM, entry->name);
if (state->qc_update)
fprintf(fp_contents_update, "%s\n", buffer);
-
continue;
}
@@ -207,31 +237,36 @@ qcheck_cb(tree_pkg_ctx *pkg_ctx, void *priv)
* do check hashes, but only print mismatched digests as
* 'ignored file'. */
if (entry->digest && S_ISREG(st.st_mode)) {
+ char *f_digest;
+ int hash_algo;
+
/* Validate digest (handles MD5 / SHA1)
* Digest-check 1/3:
- * Should we check digests? */
- char *f_digest;
- uint8_t hash_algo;
+ * should we check digests? */
switch (strlen(entry->digest)) {
- case 32: hash_algo = HASH_MD5; break;
- case 40: hash_algo = HASH_SHA1; break;
- default: hash_algo = 0; break;
+ case 32: hash_algo = (int)HASH_MD5; break;
+ case 40: hash_algo = (int)HASH_SHA1; break;
+ default: hash_algo = 0; break;
}
- if (!hash_algo) {
+ if (hash_algo == 0) {
if (state->chk_hash) {
qcprintf(" %sUNKNOWN DIGEST%s: '%s' for '%s'\n",
- RED, NORM, entry->digest, entry->name);
- ++num_files_unknown;
+ RED, NORM, entry->digest, entry->name);
+ num_files_unknown++;
} else {
- --num_files;
- ++num_files_ignored;
+ num_files--;
+ num_files_ignored++;
+ if (verbose)
+ qcprintf(" %sSKIP%s %s: unknown digest\n",
+ YELLOW, NORM, entry->name);
if (state->qc_update)
fprintf(fp_contents_update, "%s\n", buffer);
}
continue;
}
+ /* compute hash for file */
hash_cb_t hash_cb =
state->undo_prelink ? hash_cb_prelink_undo : NULL;
f_digest = hash_file_at_cb(
@@ -239,45 +274,51 @@ qcheck_cb(tree_pkg_ctx *pkg_ctx, void *priv)
entry->name + 1, hash_algo, hash_cb);
/* Digest-check 2/3:
- * Can we get a digest of the file? */
- if (!f_digest) {
- ++num_files_unknown;
+ * do we have digest of the file? */
+ if (f_digest == NULL) {
+ num_files_unknown++;
if (state->qc_update)
fprintf(fp_contents_update, "%s\n", buffer);
if (verbose)
qcprintf(" %sPERM %4o%s: %s\n",
- RED, (unsigned int)(st.st_mode & 07777),
- NORM, entry->name);
+ RED, (unsigned int)(st.st_mode & 07777),
+ NORM, entry->name);
continue;
}
/* Digest-check 3/3:
- * Does the digest equal what portage recorded? */
+ * does the digest equal what portage recorded? */
if (strcmp(entry->digest, f_digest) != 0) {
if (state->chk_hash) {
+ const char *digest_disp;
+
if (state->qc_update)
- fprintf(fp_contents_update, "obj %s %s %"PRIu64"\n",
- entry->name, f_digest, (uint64_t)st.st_mtime);
+ fprintf(fp_contents_update, "obj %s %s %llu\n",
+ entry->name, f_digest,
+ (long long int)st.st_mtime);
- const char *digest_disp;
switch (hash_algo) {
- case HASH_MD5: digest_disp = "MD5"; break;
- case HASH_SHA1: digest_disp = "SHA1"; break;
- default: digest_disp = "UNK"; break;
+ case HASH_MD5: digest_disp = "MD5"; break;
+ case HASH_SHA1: digest_disp = "SHA1"; break;
+ default: digest_disp = "UNK"; break;
}
qcprintf(" %s%s-DIGEST%s: %s",
- RED, digest_disp, NORM, entry->name);
+ RED, digest_disp, NORM, entry->name);
if (verbose)
qcprintf(" (recorded '%s' != actual '%s')",
- entry->digest, f_digest);
+ entry->digest, f_digest);
qcprintf("\n");
} else {
- --num_files;
- ++num_files_ignored;
+ num_files--;
+ num_files_ignored++;
+ if (verbose)
+ qcprintf(" %sSKIP%s %s: digest mismatch "
+ "but check disabled\n",
+ YELLOW, NORM, entry->name);
if (state->qc_update)
fprintf(fp_contents_update, "%s\n", buffer);
}
@@ -286,30 +327,44 @@ qcheck_cb(tree_pkg_ctx *pkg_ctx, void *priv)
}
}
- /* Validate mtimes */
- if (state->chk_mtime && entry->mtime && entry->mtime != st.st_mtime) {
- qcprintf(" %sMTIME%s: %s", RED, NORM, entry->name);
- if (verbose)
- qcprintf(" (recorded '%"PRIu64"' != actual '%"PRIu64"')",
- (uint64_t)entry->mtime, (uint64_t)st.st_mtime);
- qcprintf("\n");
-
- /* Update mtime */
- if (state->qc_update) {
- if (entry->type == CONTENTS_SYM) {
- fprintf(fp_contents_update, "sym %s -> %s %"PRIu64"\n",
- entry->name, entry->sym_target,
- (uint64_t)st.st_mtime);
- } else {
- fprintf(fp_contents_update, "obj %s %s %"PRIu64"\n",
- entry->name, entry->digest, (uint64_t)st.st_mtime);
+ /* validate mtimes */
+ if (entry->mtime && entry->mtime != st.st_mtime) {
+ if (state->chk_mtime) {
+ qcprintf(" %sMTIME%s: %s", RED, NORM, entry->name);
+ if (verbose)
+ qcprintf(" (recorded '%llu' != actual '%llu')",
+ (long long int)entry->mtime,
+ (long long int)st.st_mtime);
+ qcprintf("\n");
+
+ /* Update mtime */
+ if (state->qc_update) {
+ if (entry->type == CONTENTS_SYM) {
+ fprintf(fp_contents_update, "sym %s -> %s %llu\n",
+ entry->name, entry->sym_target,
+ (long long int)st.st_mtime);
+ } else {
+ fprintf(fp_contents_update, "obj %s %s %llu\n",
+ entry->name, entry->digest,
+ (long long int)st.st_mtime);
+ }
}
- }
- continue;
+ continue;
+ } else {
+ num_files--;
+ num_files_ignored++;
+ if (verbose)
+ qcprintf(" %sSKIP%s %s: mtime mismatch "
+ "but check disabled\n",
+ YELLOW, NORM, entry->name);
+ if (state->qc_update)
+ fprintf(fp_contents_update, "%s\n", buffer);
+ continue;
+ }
}
- /* Success! */
+ /* success! */
if (state->qc_update)
fprintf(fp_contents_update, "%s\n", buffer);
diff --git a/tests/qcheck/list05.good b/tests/qcheck/list05.good
index 688c177..bb1e169 100644
--- a/tests/qcheck/list05.good
+++ b/tests/qcheck/list05.good
@@ -6,6 +6,6 @@ Checking a-b/pkg ...
AFK: /missing-dir
AFK: /missing-dir/missing-file
AFK: /missing-dir/missing-sym
- * 4 out of 11 files are good (2 files were ignored)
+ * 3 out of 10 files are good (3 files were ignored)
Checking virtual/pkg ...
* 0 out of 0 files are good
diff --git a/tests/qcheck/list07.good b/tests/qcheck/list07.good
index 847b0b5..c80a073 100644
--- a/tests/qcheck/list07.good
+++ b/tests/qcheck/list07.good
@@ -1,4 +1,4 @@
Checking a-b/pkg ...
- * 4 out of 4 files are good (9 files were ignored)
+ * 3 out of 3 files are good (10 files were ignored)
Checking virtual/pkg ...
* 0 out of 0 files are good
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2022-04-09 11:32 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-04-09 11:32 [gentoo-commits] proj/portage-utils:master commit in: tests/qcheck/, / Fabian Groffen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox