From 7d1d6920945b127e460b39fa3ebf359cd21d19ed Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 3 Jan 2025 11:33:17 +0000 Subject: [PATCH] build: Move filtering dependencies into the package object Signed-off-by: Michael Tremer --- src/pakfire/build.c | 124 +++++++++------------------------------- src/pakfire/package.c | 130 ++++++++++++++++++++++++++++++++++++++++++ src/pakfire/package.h | 3 + 3 files changed, 161 insertions(+), 96 deletions(-) diff --git a/src/pakfire/build.c b/src/pakfire/build.c index b58556b77..383ba1383 100644 --- a/src/pakfire/build.c +++ b/src/pakfire/build.c @@ -25,9 +25,6 @@ #include #include -#define PCRE2_CODE_UNIT_WIDTH 8 -#include - #include #include #include @@ -314,38 +311,11 @@ struct pakfire_find_deps_ctx { int dep; struct pakfire_scriptlet* scriptlet; int class; - const pcre2_code* filter; struct pakfire_filelist* filelist; unsigned int i; }; -static int pakfire_build_make_filter(struct pakfire_build* build, pcre2_code** regex, - struct pakfire_parser* makefile, const char* namespace, const char* filter) { - char* pattern = NULL; - int r = 0; - - // Fetch the pattern - pattern = pakfire_parser_get(makefile, namespace, filter); - - // Nothing if to if there is no or an empty pattern - if (!pattern || !*pattern) - goto ERROR; - - DEBUG(build->ctx, "Found filter for %s: %s\n", filter, pattern); - - // Compile the regular expression - r = pakfire_compile_regex(build->ctx, regex, pattern); - if (r) - goto ERROR; - -ERROR: - if (pattern) - free(pattern); - - return r; -} - static ssize_t pakfire_build_send_filelist( struct pakfire_ctx* ctx, void* data, char* buffer, size_t length) { struct pakfire_find_deps_ctx* p = (struct pakfire_find_deps_ctx*)data; @@ -408,7 +378,6 @@ static int pakfire_build_process_deps(struct pakfire_ctx* ctx, void* data, const char* buffer, const size_t length) { const struct pakfire_find_deps_ctx* p = (struct pakfire_find_deps_ctx*)data; char dep[PATH_MAX]; - pcre2_match_data* match = NULL; int r = 0; // Nothing to do for an empty buffer @@ -433,45 +402,6 @@ static int pakfire_build_process_deps(struct pakfire_ctx* ctx, void* data, goto SKIP; } - // Check if this dependency should be filtered - if (p->filter) { - match = pcre2_match_data_create_from_pattern(p->filter, NULL); - if (!match) { - ERROR(ctx, "Could not allocate PCRE match data: %m\n"); - goto ERROR; - } - - // Perform matching - r = pcre2_jit_match(p->filter, (PCRE2_SPTR)dep, length - 1, - 0, 0, match, NULL); - - // No match - if (r == PCRE2_ERROR_NOMATCH) { - // Fall through... - - // Handle any errors - } else if (r < 0) { - char error[120]; - - // Fetch the error message - r = pcre2_get_error_message(r, (PCRE2_UCHAR*)error, sizeof(error)); - if (r < 0) { - ERROR(ctx, "Could not fetch PCRE error message: %m\n"); - r = -errno; - goto ERROR; - } - - ERROR(ctx, "Could not match the filter: %s\n", error); - r = -errno; - goto ERROR; - - // Match! - } else { - DEBUG(ctx, "Skipping dependency that has been filtered: %s\n", dep); - goto SKIP; - } - } - // Add dependency r = pakfire_package_add_dep(p->pkg, p->dep, "%s", dep); if (r < 0) { @@ -491,8 +421,6 @@ SKIP: r = length; ERROR: - if (match) - pcre2_match_data_free(match); return r; } @@ -738,7 +666,7 @@ static int __pakfire_build_find_requires( } static int pakfire_build_find_requires(struct pakfire_build* build, - struct pakfire_package* pkg, struct pakfire_filelist* filelist, const pcre2_code* filter) { + struct pakfire_package* pkg, struct pakfire_filelist* filelist) { struct pakfire_find_deps_ctx deps = { .build = build, .pkg = pkg, @@ -755,14 +683,13 @@ static int pakfire_build_find_requires(struct pakfire_build* build, */ static int pakfire_build_find_deps(struct pakfire_build* build, struct pakfire_package* pkg, int dep, const char* script, - struct pakfire_filelist* filelist, int class, const pcre2_code* filter) { + struct pakfire_filelist* filelist, int class) { // Construct the context struct pakfire_find_deps_ctx ctx = { .build = build, .pkg = pkg, .dep = dep, .class = class, - .filter = filter, // Filelist .filelist = filelist, @@ -794,60 +721,65 @@ static int pakfire_build_find_deps(struct pakfire_build* build, static int pakfire_build_find_dependencies(struct pakfire_build* build, struct pakfire_parser* makefile, const char* namespace, struct pakfire_package* pkg, struct pakfire_filelist* filelist) { - pcre2_code* filter_provides = NULL; - pcre2_code* filter_requires = NULL; + char* filter_provides = NULL; + char* filter_requires = NULL; int r; // Fetch the provides filter - r = pakfire_build_make_filter(build, &filter_provides, - makefile, namespace, "filter_provides"); - if (r) { - ERROR(build->ctx, "Provides filter is broken: %m\n"); - goto ERROR; + filter_provides = pakfire_parser_get(makefile, namespace, "filter_provides"); + if (filter_provides) { + r = pakfire_package_add_dep_filter(pkg, PAKFIRE_PKG_PROVIDES, filter_provides); + if (r < 0) + goto ERROR; } // Fetch the requires filter - r = pakfire_build_make_filter(build, &filter_requires, - makefile, namespace, "filter_requires"); - if (r) { - ERROR(build->ctx, "Requires filter is broken: %m\n"); - goto ERROR; + filter_requires = pakfire_parser_get(makefile, namespace, "filter_requires"); + if (filter_requires) { + r = pakfire_package_add_dep_filter(pkg, PAKFIRE_PKG_REQUIRES, filter_requires); + if (r < 0) + goto ERROR; } // Find all provides r = pakfire_build_find_deps(build, pkg, - PAKFIRE_PKG_PROVIDES, "find-provides", filelist, 0, filter_provides); + PAKFIRE_PKG_PROVIDES, "find-provides", filelist, 0); if (r) goto ERROR; // Find all Perl provides r = pakfire_build_find_deps(build, pkg, - PAKFIRE_PKG_PROVIDES, "perl.prov", filelist, PAKFIRE_FILE_PERL, filter_provides); + PAKFIRE_PKG_PROVIDES, "perl.prov", filelist, PAKFIRE_FILE_PERL); if (r) goto ERROR; // Find all requires - r = pakfire_build_find_requires(build, pkg, filelist, filter_requires); + r = pakfire_build_find_requires(build, pkg, filelist); if (r < 0) goto ERROR; // XXX LEGACY CODE r = pakfire_build_find_deps(build, pkg, - PAKFIRE_PKG_REQUIRES, "find-requires", filelist, 0, filter_requires); + PAKFIRE_PKG_REQUIRES, "find-requires", filelist, 0); if (r) goto ERROR; // Find all Perl requires r = pakfire_build_find_deps(build, pkg, - PAKFIRE_PKG_REQUIRES, "perl.req", filelist, PAKFIRE_FILE_PERL, filter_requires); + PAKFIRE_PKG_REQUIRES, "perl.req", filelist, PAKFIRE_FILE_PERL); if (r) goto ERROR; ERROR: - if (filter_provides) - pcre2_code_free(filter_provides); - if (filter_requires) - pcre2_code_free(filter_requires); + if (filter_provides) { + pakfire_package_add_dep_filter(pkg, PAKFIRE_PKG_PROVIDES, NULL); + free(filter_provides); + } + + if (filter_requires) { + pakfire_package_add_dep_filter(pkg, PAKFIRE_PKG_REQUIRES, NULL); + free(filter_requires); + } return r; } diff --git a/src/pakfire/package.c b/src/pakfire/package.c index b0958a558..848ee074e 100644 --- a/src/pakfire/package.c +++ b/src/pakfire/package.c @@ -27,6 +27,10 @@ #include +// PCRE2 +#define PCRE2_CODE_UNIT_WIDTH 8 +#include + #include #include #include @@ -65,6 +69,11 @@ struct pakfire_package { char filename[NAME_MAX]; char path[PATH_MAX]; char cache_path[PATH_MAX]; + + struct { + pcre2_code* requires; + pcre2_code* provides; + } filters; }; static Solvable* get_solvable(struct pakfire_package* pkg) { @@ -263,6 +272,10 @@ ERROR: } static void pakfire_package_free(struct pakfire_package* pkg) { + if (pkg->filters.requires) + pcre2_code_free(pkg->filters.requires); + if (pkg->filters.provides) + pcre2_code_free(pkg->filters.provides); if (pkg->repo) pakfire_repo_unref(pkg->repo); if (pkg->pakfire) @@ -1369,6 +1382,94 @@ SUCCESS: return ret; } +int pakfire_package_add_dep_filter(struct pakfire_package* pkg, + const enum pakfire_package_key key, const char* pattern) { + pcre2_code* filter = NULL; + int r; + + // Compile the filter + if (pattern) { + r = pakfire_compile_regex(pkg->ctx, &filter, pattern); + if (r < 0) { + ERROR(pkg->ctx, "Could not install dependency filter for %s: %s\n", + pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA), pattern); + return r; + } + } + + switch (key) { + case PAKFIRE_PKG_PROVIDES: + if (pkg->filters.provides) + pcre2_code_free(pkg->filters.provides); + + pkg->filters.provides = filter; + break; + + case PAKFIRE_PKG_REQUIRES: + if (pkg->filters.requires) + pcre2_code_free(pkg->filters.requires); + + pkg->filters.requires = filter; + break; + + default: + pcre2_code_free(filter); + + return -EINVAL; + } + + return 0; +} + +static int pakfire_package_filter_dep(struct pakfire_package* pkg, + const pcre2_code* filter, const char* dep) { + pcre2_match_data* match = NULL; + char error[120]; + int r; + + // Prepare match + match = pcre2_match_data_create_from_pattern(filter, NULL); + if (!match) { + ERROR(pkg->ctx, "Could not allocate PCRE match data: %m\n"); + r = -errno; + goto ERROR; + } + + // Perform matching + r = pcre2_jit_match(filter, (PCRE2_SPTR)dep, -1, 0, 0, match, NULL); + if (r < 0) { + switch (r) { + case PCRE2_ERROR_NOMATCH: + r = 0; + goto ERROR; + + default: + // Fetch the error message + r = pcre2_get_error_message(r, (PCRE2_UCHAR*)error, sizeof(error)); + if (r < 0) { + ERROR(pkg->ctx, "Could not fetch PCRE error message: %m\n"); + r = -errno; + goto ERROR; + } + + ERROR(pkg->ctx, "Could not match the filter: %s\n", error); + r = -EINVAL; + goto ERROR; + } + } + + // Match! + DEBUG(pkg->ctx, "%s: Dependency '%s' has been filtered\n", + pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA), dep); + r = 1; + +ERROR: + if (match) + pcre2_match_data_free(match); + + return r; +} + int pakfire_package_add_dep(struct pakfire_package* pkg, const enum pakfire_package_key key, const char* format, ...) { char buffer[PATH_MAX]; @@ -1386,6 +1487,35 @@ int pakfire_package_add_dep(struct pakfire_package* pkg, if (pakfire_string_startswith(buffer, "#")) return 0; + // Apply filters + switch (key) { + case PAKFIRE_PKG_PROVIDES: + if (pkg->filters.provides) { + r = pakfire_package_filter_dep(pkg, pkg->filters.provides, buffer); + if (r < 0) + return r; + + // Filtered + else if (r == 1) + return 0; + } + break; + + case PAKFIRE_PKG_REQUIRES: + if (pkg->filters.requires) { + r = pakfire_package_filter_dep(pkg, pkg->filters.requires, buffer); + if (r < 0) + return r; + + // Filtered + else if (r == 1) + return 0; + } + + default: + break; + } + // Parse the dependency Id id = pakfire_str2dep(pkg->pakfire, buffer); if (!id) { diff --git a/src/pakfire/package.h b/src/pakfire/package.h index d1f8519c3..87e52ee4a 100644 --- a/src/pakfire/package.h +++ b/src/pakfire/package.h @@ -173,6 +173,9 @@ int pakfire_package_is_installed(struct pakfire_package* pkg); int pakfire_package_append_file(struct pakfire_package* pkg, const char* path); // Dependencies +int pakfire_package_add_dep_filter(struct pakfire_package* pkg, + const enum pakfire_package_key key, const char* pattern); + int pakfire_package_add_dep(struct pakfire_package* pkg, const enum pakfire_package_key key, const char* format, ...) __attribute__((format(printf, 3, 4))); -- 2.47.2