#include <unistd.h>
#include <uuid/uuid.h>
-#define PCRE2_CODE_UNIT_WIDTH 8
-#include <pcre2.h>
-
#include <pakfire/build.h>
#include <pakfire/cgroup.h>
#include <pakfire/config.h>
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;
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
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) {
r = length;
ERROR:
- if (match)
- pcre2_match_data_free(match);
return r;
}
}
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,
*/
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,
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;
}
#include <json.h>
+// PCRE2
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+
#include <solv/evr.h>
#include <solv/pool.h>
#include <solv/repo.h>
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) {
}
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)
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];
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) {