From f05c78008b1754a79e31e793a67d07ed8f5d11bc Mon Sep 17 00:00:00 2001 From: sbesl Date: Sat, 10 Aug 2019 00:31:57 +0200 Subject: Make qfile also check the prune lib registry Modifications by Fabian Groffen : - indentation fixes - declarations go on top - no C99 features - adapt style to 0.80 release Signed-off-by: Fabian Groffen --- qfile.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 2 deletions(-) diff --git a/qfile.c b/qfile.c index bc5c9ac..63b47da 100644 --- a/qfile.c +++ b/qfile.c @@ -20,7 +20,7 @@ #include "rmspace.h" #include "tree.h" -#define QFILE_FLAGS "F:doRx:S" COMMON_FLAGS +#define QFILE_FLAGS "F:doRx:SP" COMMON_FLAGS static struct option const qfile_long_opts[] = { {"format", a_argument, NULL, 'F'}, {"slots", no_argument, NULL, 'S'}, @@ -28,6 +28,7 @@ static struct option const qfile_long_opts[] = { {"dir", no_argument, NULL, 'd'}, {"orphans", no_argument, NULL, 'o'}, {"exclude", a_argument, NULL, 'x'}, + {"skip-plibreg",no_argument, NULL, 'P'}, COMMON_LONG_OPTS }; static const char * const qfile_opts_help[] = { @@ -37,6 +38,7 @@ static const char * const qfile_opts_help[] = { "Also match directories for single component arguments", "List orphan files", "Don't look in package (used with --orphans)", + "Don't look in the prunelib registry", COMMON_OPTS_HELP }; #define qfile_usage(ret) usage(ret, QFILE_FLAGS, qfile_long_opts, qfile_opts_help, NULL, lookup_applet_idx("qfile")) @@ -53,6 +55,7 @@ typedef struct { char **dirnames; char **realdirnames; short *non_orphans; + int *results; } qfile_args_t; struct qfile_opt_state { @@ -69,10 +72,88 @@ struct qfile_opt_state { bool basename; bool orphans; bool assume_root_prefix; + bool skip_plibreg; const char *format; bool need_full_atom; }; +/* + * As a final step, check if file is in the plib_reg + */ +static int qfile_check_plibreg(void *priv) +{ + struct qfile_opt_state *state = priv; + + char fn_plibreg[_Q_PATH_MAX]; + int fd_plibreg; + FILE *fp_plibreg; + struct stat cst; + + char file[_Q_PATH_MAX]; + char *line = NULL; + size_t len = 0; + int found = 0; + int i; + + qfile_args_t *args = &state->args; + char **base_names = args->basenames; + char **dir_names = args->dirnames; + short *non_orphans = args->non_orphans; + int *results = args->results; + + /* Open plibreg */ + snprintf(fn_plibreg, _Q_PATH_MAX, "%s%s", + CONFIG_EPREFIX, "var/lib/portage/preserved_libs_registry"); + fp_plibreg = NULL; + fd_plibreg = open(fn_plibreg, O_RDONLY|O_CLOEXEC, 0); + if (fd_plibreg == -1) + return 0; + if (fstat(fd_plibreg, &cst)) { + close(fd_plibreg); + return 0; + } + if ((fp_plibreg = fdopen(fd_plibreg, "r")) == NULL) { + close(fd_plibreg); + return 0; + } + + for (i = 0; i < args->length; i++) { + if (base_names[i] == NULL) + continue; + if (non_orphans && non_orphans[i]) + continue; + if (results[i] == 1) + continue; + + if (dir_names[i] != NULL) + snprintf(file, sizeof(file), "%s/%s", dir_names[i], base_names[i]); + else + snprintf(file, sizeof(file), "%s", base_names[i]); + + while (getline(&line, &len, fp_plibreg) != -1) + if (strstr(line, file) != NULL) { + found++; + if (!quiet) + printf("%splib_registry%s\n", BLUE, NORM); + else + printf("%splib_registry%s: %s\n", BLUE, NORM, file); + } + } + + if (line) + free(line); + + return found; +} + +/* + * 1. Do package exclusion tests + * 2. Run through CONTENTS file, perform tests and fail-by-continue + * 3. On success bump and return retvalue 'found' + * + * We assume the people calling us have chdir(/var/db/pkg) and so + * we use relative paths throughout here. + */ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv) { struct qfile_opt_state *state = priv; @@ -88,6 +169,7 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv) char **dir_names = args->dirnames; char **real_dir_names = args->realdirnames; short *non_orphans = args->non_orphans; + int *results = args->results; int found = 0; /* If exclude_pkg is not NULL, check it. We are looking for files @@ -116,6 +198,7 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv) if (fp == NULL) goto qlist_done; + /* Run through CONTENTS file */ while (getline(&state->buf, &state->buflen, fp) != -1) { size_t dirname_len; contents_entry *e; @@ -224,6 +307,9 @@ static int qfile_cb(tree_pkg_ctx *pkg_ctx, void *priv) } else { non_orphans[i] = 1; } + + /* Success */ + results[i] = 1; found++; } } @@ -250,6 +336,7 @@ static void destroy_qfile_args(qfile_args_t *qfile_args) free(qfile_args->dirnames); free(qfile_args->realdirnames); free(qfile_args->non_orphans); + free(qfile_args->results); memset(qfile_args, 0, sizeof(qfile_args_t)); } @@ -268,6 +355,7 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st char **basenames = NULL; char **dirnames = NULL; char **realdirnames = NULL; + int *results = NULL; char tmppath[_Q_PATH_MAX]; char abspath[_Q_PATH_MAX]; @@ -279,6 +367,7 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st basenames = xcalloc(argc, sizeof(char*)); dirnames = xcalloc(argc, sizeof(char*)); realdirnames = xcalloc(argc, sizeof(char*)); + results = xcalloc(argc, sizeof(int)); for (i = 0; i < argc; ++i) { /* Record basename, but if it is ".", ".." or "/" */ @@ -375,6 +464,7 @@ prepare_qfile_args(const int argc, const char **argv, struct qfile_opt_state *st args->dirnames = dirnames; args->realdirnames = realdirnames; args->length = argc; + args->results = results; if (state->orphans) args->non_orphans = xcalloc(argc, sizeof(short)); @@ -390,6 +480,7 @@ int qfile_main(int argc, char **argv) .basename = false, .orphans = false, .assume_root_prefix = false, + .skip_plibreg = false, .format = NULL, }; int i, nb_of_queries, found = 0; @@ -403,6 +494,7 @@ int qfile_main(int argc, char **argv) case 'd': state.basename = true; break; case 'o': state.orphans = true; break; case 'R': state.assume_root_prefix = true; break; + case 'P': state.skip_plibreg = true; break; case 'x': if (state.exclude_pkg) err("--exclude can only be used once."); @@ -471,7 +563,8 @@ int qfile_main(int argc, char **argv) /* Prepare the qfile(...) arguments structure */ nb_of_queries = prepare_qfile_args(argc, (const char **) argv, &state); - /* Now do the actual `qfile` checking */ + + /* Now do the actual `qfile` checking by looking at CONTENTS of all pkgs */ if (nb_of_queries > 0) { tree_ctx *vdb = tree_open_vdb(portroot, portvdb); if (vdb != NULL) { @@ -480,6 +573,14 @@ int qfile_main(int argc, char **argv) } } + /* Also check the prune lib registry. + * But only for files we otherwise couldn't account for. If we'd + * check plib_reg for all files, we would get duplicate messages for + * files that were re-added to CONTENTS files after a version + * upgrade (which are also recorded in plib_reg). */ + if (nb_of_queries > 0 && !state.skip_plibreg) + found += qfile_check_plibreg(&state); + if (state.args.non_orphans) { /* display orphan files */ for (i = 0; i < state.args.length; i++) { -- cgit v1.2.3-65-gdbad