#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/dependencies.h>
int dep;
struct pakfire_scriptlet* scriptlet;
const char* pattern;
+ 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->pakfire, "Found filter for %s: %s\n", filter, pattern);
+
+ // Compile the regular expression
+ r = pakfire_compile_regex(build->pakfire, regex, pattern);
+ if (r)
+ goto ERROR;
+
+ERROR:
+ if (pattern)
+ free(pattern);
+
+ return r;
+}
+
static int pakfire_build_send_filelist(struct pakfire* pakfire, void* data, int fd) {
struct pakfire_find_deps_ctx* ctx = (struct pakfire_find_deps_ctx*)data;
struct pakfire_file* file = NULL;
void* data, int priority, const char* buffer, const size_t length) {
const struct pakfire_find_deps_ctx* ctx = (struct pakfire_find_deps_ctx*)data;
char dep[PATH_MAX];
- int r;
+ pcre2_match_data* match = NULL;
+ int r = 0;
// Nothing to do for an empty buffer
if (!buffer || !*buffer)
goto SKIP;
}
+ // Check if this dependency should be filtered
+ if (ctx->filter) {
+ match = pcre2_match_data_create_from_pattern(ctx->filter, NULL);
+ if (!match) {
+ ERROR(pakfire, "Could not allocate PCRE match data: %m\n");
+ goto ERROR;
+ }
+
+ // Perform matching
+ r = pcre2_jit_match(ctx->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(pakfire, "Could not fetch PCRE error message: %m\n");
+ r = 1;
+ goto ERROR;
+ }
+
+ ERROR(pakfire, "Could not match the filter: %s\n", error);
+ r = 1;
+ goto ERROR;
+
+ // Match!
+ } else {
+ DEBUG(pakfire, "Skipping dependency that has been filtered: %s\n", dep);
+ r = 0;
+ goto ERROR;
+ }
+ }
+
// Add dependency
r = pakfire_package_add_dep(ctx->pkg, ctx->dep, buffer);
if (r) {
break;
}
- return 0;
+ goto ERROR;
SKIP:
DEBUG(pakfire, "Skipping dependency that is provided by the package itself: %s\n", dep);
- return 0;
+ERROR:
+ if (match)
+ pcre2_match_data_free(match);
+
+ return r;
}
/*
*/
static int pakfire_build_find_deps(struct pakfire_build* build,
struct pakfire_package* pkg, int dep, const char* script,
- struct pakfire_filelist* filelist, const char* pattern) {
+ struct pakfire_filelist* filelist, const char* pattern, const pcre2_code* filter) {
// Construct the context
struct pakfire_find_deps_ctx ctx = {
.pkg = pkg,
.dep = dep,
.pattern = pattern,
+ .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;
int r;
+ // Fetch the provides filter
+ r = pakfire_build_make_filter(build, &filter_provides,
+ makefile, namespace, "filter_provides");
+ if (r) {
+ ERROR(build->pakfire, "Provides filter is broken: %m\n");
+ goto ERROR;
+ }
+
+ // Fetch the requires filter
+ r = pakfire_build_make_filter(build, &filter_requires,
+ makefile, namespace, "filter_requires");
+ if (r) {
+ ERROR(build->pakfire, "Requires filter is broken: %m\n");
+ goto ERROR;
+ }
+
// Find all provides
r = pakfire_build_find_deps(build, pkg,
- PAKFIRE_PKG_PROVIDES, "find-provides", filelist, NULL);
+ PAKFIRE_PKG_PROVIDES, "find-provides", filelist, NULL, filter_provides);
if (r)
- return r;
+ goto ERROR;
// Find all Perl provides
r = pakfire_build_find_deps(build, pkg,
- PAKFIRE_PKG_PROVIDES, "perl.prov", filelist, "*.pm");
+ PAKFIRE_PKG_PROVIDES, "perl.prov", filelist, "*.pm", filter_provides);
if (r)
- return r;
+ goto ERROR;
// Find all requires
r = pakfire_build_find_deps(build, pkg,
- PAKFIRE_PKG_REQUIRES, "find-requires", filelist, NULL);
+ PAKFIRE_PKG_REQUIRES, "find-requires", filelist, NULL, filter_requires);
if (r)
- return r;
+ goto ERROR;
// Find all Perl requires
r = pakfire_build_find_deps(build, pkg,
- PAKFIRE_PKG_REQUIRES, "perl.req", filelist, "*.pm");
+ PAKFIRE_PKG_REQUIRES, "perl.req", filelist, "*.pm", filter_requires);
if (r)
- return r;
+ goto ERROR;
- return 0;
+ERROR:
+ if (filter_provides)
+ pcre2_code_free(filter_provides);
+ if (filter_requires)
+ pcre2_code_free(filter_requires);
+
+ return r;
}
static int append_to_array(char*** array, const char* s) {
pakfire_filelist_dump(filelist, 1);
// Find dependencies
- r = pakfire_build_find_dependencies(build, pkg, filelist);
+ r = pakfire_build_find_dependencies(build, makefile, namespace, pkg, filelist);
if (r) {
ERROR(build->pakfire, "Finding dependencies failed: %m\n");
goto ERROR;