From 3285d136ba052ac54769246c4757064d1c1f1aaf Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sat, 26 Oct 2024 12:18:10 +0000 Subject: [PATCH] path: Move the match function into the path library Signed-off-by: Michael Tremer --- src/libpakfire/include/pakfire/path.h | 2 + src/libpakfire/include/pakfire/util.h | 1 - src/libpakfire/linter-file.c | 2 +- src/libpakfire/path.c | 87 +++++++++++++++++++++++++++ src/libpakfire/util.c | 87 --------------------------- tests/libpakfire/path.c | 37 ++++++++++++ tests/libpakfire/util.c | 37 ------------ 7 files changed, 127 insertions(+), 126 deletions(-) diff --git a/src/libpakfire/include/pakfire/path.h b/src/libpakfire/include/pakfire/path.h index 820b02c5c..0e2693adf 100644 --- a/src/libpakfire/include/pakfire/path.h +++ b/src/libpakfire/include/pakfire/path.h @@ -53,4 +53,6 @@ int pakfire_path_is_absolute(const char* s); __pakfire_path_absolute(path, sizeof(path), s) int __pakfire_path_absolute(char* buffer, const size_t length, const char* s); +int pakfire_path_match(const char* p, const char* s); + #endif /* PAKFIRE_PATH_H */ diff --git a/src/libpakfire/include/pakfire/util.h b/src/libpakfire/include/pakfire/util.h index 59011cdd9..befce026f 100644 --- a/src/libpakfire/include/pakfire/util.h +++ b/src/libpakfire/include/pakfire/util.h @@ -50,7 +50,6 @@ static inline void* pakfire_realloc(void* p, size_t size) { } int pakfire_path_exists(const char* path); -int pakfire_path_match(const char* p, const char* s); time_t pakfire_path_age(const char* path); int pakfire_path_strip_extension(char* path); diff --git a/src/libpakfire/linter-file.c b/src/libpakfire/linter-file.c index 4a9f173da..35fa67777 100644 --- a/src/libpakfire/linter-file.c +++ b/src/libpakfire/linter-file.c @@ -28,8 +28,8 @@ #include #include #include +#include #include -#include struct pakfire_linter_file { struct pakfire_ctx* ctx; diff --git a/src/libpakfire/path.c b/src/libpakfire/path.c index 1bf0c0255..7331bb245 100644 --- a/src/libpakfire/path.c +++ b/src/libpakfire/path.c @@ -546,3 +546,90 @@ ERROR: return r; } + +/* + This function will handle any stars in the pattern matching + + stars will be set to non-zero if we encountered a double star +*/ +static int __pakfire_path_match_star(const char* p, const char* s) { + unsigned int stars = 0; + int r; + + // Count how many stars we found + while (p && *p == '*') { + // Consume the star + p++; + + // Increment the counter + stars++; + } + + // We do not allow more than two stars + if (stars > 2) { + errno = EINVAL; + return -1; + } + + // Consume the string... + for (; *s; s++) { + // Found slash! + if (*s == '/' && stars == 1) + return pakfire_path_match(p, s); + + // Otherwise read as many characters as possible + r = pakfire_path_match(p, s); + if (r) + return r; + } + + // The pattern has not entirely been consumed + if (p && *p) + return 0; + + // If we reached the end of the string, * has consumed everything + return 1; +} + +/* + This is our custom implementation of fnmatch() + which supports ** and stops at slashes. +*/ +int pakfire_path_match(const char* p, const char* s) { + // Empty pattern matches nothing + if (!p || !*p) + return 0; + + // Consume the pattern and string... + for (; *p; p++, s++) { + switch (*p) { + // Match any character + case '?': + // No match if we reached the end + if (!*s) + return 0; + + continue; + + // Match multiple characters + case '*': + return __pakfire_path_match_star(p, s); + + // All other characters + default: + // Character matches + if (*s == *p) + continue; + + // No match + return 0; + } + } + + // There are unmatched characters left + if (*s) + return 0; + + // We reached the end of the string and all characters matched + return 1; +} diff --git a/src/libpakfire/util.c b/src/libpakfire/util.c index 56c6bea5e..c6791e355 100644 --- a/src/libpakfire/util.c +++ b/src/libpakfire/util.c @@ -83,93 +83,6 @@ int pakfire_path_exists(const char* path) { return !access(path, F_OK); } -/* - This function will handle any stars in the pattern matching - - stars will be set to non-zero if we encountered a double star -*/ -static int __pakfire_path_match_star(const char* p, const char* s) { - unsigned int stars = 0; - int r; - - // Count how many stars we found - while (p && *p == '*') { - // Consume the star - p++; - - // Increment the counter - stars++; - } - - // We do not allow more than two stars - if (stars > 2) { - errno = EINVAL; - return -1; - } - - // Consume the string... - for (; *s; s++) { - // Found slash! - if (*s == '/' && stars == 1) - return pakfire_path_match(p, s); - - // Otherwise read as many characters as possible - r = pakfire_path_match(p, s); - if (r) - return r; - } - - // The pattern has not entirely been consumed - if (p && *p) - return 0; - - // If we reached the end of the string, * has consumed everything - return 1; -} - -/* - This is our custom implementation of fnmatch() - which supports ** and stops at slashes. -*/ -int pakfire_path_match(const char* p, const char* s) { - // Empty pattern matches nothing - if (!p || !*p) - return 0; - - // Consume the pattern and string... - for (; *p; p++, s++) { - switch (*p) { - // Match any character - case '?': - // No match if we reached the end - if (!*s) - return 0; - - continue; - - // Match multiple characters - case '*': - return __pakfire_path_match_star(p, s); - - // All other characters - default: - // Character matches - if (*s == *p) - continue; - - // No match - return 0; - } - } - - // There are unmatched characters left - if (*s) - return 0; - - // We reached the end of the string and all characters matched - return 1; -} - time_t pakfire_path_age(const char* path) { struct stat st; diff --git a/tests/libpakfire/path.c b/tests/libpakfire/path.c index c7214c46f..2ca728726 100644 --- a/tests/libpakfire/path.c +++ b/tests/libpakfire/path.c @@ -142,6 +142,42 @@ FAIL: return EXIT_FAILURE; } +static int test_path_match(const struct test* t) { + // Simple string match + ASSERT_TRUE(pakfire_path_match("/abc", "/abc")); + + // Simple negative string match + ASSERT_FALSE(pakfire_path_match("/abc", "/def")); + + // Simple star match + ASSERT_TRUE(pakfire_path_match("/usr/*", "/usr/bin")); + ASSERT_FALSE(pakfire_path_match("/usr/*", "/usr/bin/bash")); + + // Double star match + ASSERT_TRUE(pakfire_path_match("/usr/**", "/usr/bin")); + ASSERT_TRUE(pakfire_path_match("/usr/**", "/usr/bin/bash")); + + // Tripe star matches are invalid + ASSERT_ERRNO(pakfire_path_match("/usr/***", "/usr/bin"), EINVAL); + ASSERT_ERRNO(pakfire_path_match("/usr/***", "/usr/bin/bash"), EINVAL); + + // Partial paths shouldn't match + ASSERT_FALSE(pakfire_path_match("/usr", "/usr/bin/bash")); + + // Check for stars in the middle + ASSERT_TRUE(pakfire_path_match("/usr/lib64/*.so.*", "/usr/lib64/libblah.so.1")); + ASSERT_TRUE(pakfire_path_match("/usr/lib64/**/*.so", "/usr/lib64/blah/module.so")); + ASSERT_FALSE(pakfire_path_match("/usr/lib64/*.so.*", "/usr/lib64/beep")); + + // Relatve vs. absolute? + ASSERT_FALSE(pakfire_path_match("/usr/lib/*.so", "relative-path")); + + return EXIT_SUCCESS; + +FAIL: + return EXIT_FAILURE; +} + int main(int argc, const char* argv[]) { testsuite_add_test(test_path_normalize, 0); testsuite_add_test(test_path_append, 0); @@ -149,6 +185,7 @@ int main(int argc, const char* argv[]) { testsuite_add_test(test_path_basename, 0); testsuite_add_test(test_path_dirname, 0); testsuite_add_test(test_path_relative, 0); + testsuite_add_test(test_path_match, 0); return testsuite_run(argc, argv); } diff --git a/tests/libpakfire/util.c b/tests/libpakfire/util.c index ca9fde5a7..ea4144d0f 100644 --- a/tests/libpakfire/util.c +++ b/tests/libpakfire/util.c @@ -50,42 +50,6 @@ FAIL: return EXIT_FAILURE; } -static int test_path_match(const struct test* t) { - // Simple string match - ASSERT_TRUE(pakfire_path_match("/abc", "/abc")); - - // Simple negative string match - ASSERT_FALSE(pakfire_path_match("/abc", "/def")); - - // Simple star match - ASSERT_TRUE(pakfire_path_match("/usr/*", "/usr/bin")); - ASSERT_FALSE(pakfire_path_match("/usr/*", "/usr/bin/bash")); - - // Double star match - ASSERT_TRUE(pakfire_path_match("/usr/**", "/usr/bin")); - ASSERT_TRUE(pakfire_path_match("/usr/**", "/usr/bin/bash")); - - // Tripe star matches are invalid - ASSERT_ERRNO(pakfire_path_match("/usr/***", "/usr/bin"), EINVAL); - ASSERT_ERRNO(pakfire_path_match("/usr/***", "/usr/bin/bash"), EINVAL); - - // Partial paths shouldn't match - ASSERT_FALSE(pakfire_path_match("/usr", "/usr/bin/bash")); - - // Check for stars in the middle - ASSERT_TRUE(pakfire_path_match("/usr/lib64/*.so.*", "/usr/lib64/libblah.so.1")); - ASSERT_TRUE(pakfire_path_match("/usr/lib64/**/*.so", "/usr/lib64/blah/module.so")); - ASSERT_FALSE(pakfire_path_match("/usr/lib64/*.so.*", "/usr/lib64/beep")); - - // Relatve vs. absolute? - ASSERT_FALSE(pakfire_path_match("/usr/lib/*.so", "relative-path")); - - return EXIT_SUCCESS; - -FAIL: - return EXIT_FAILURE; -} - static int test_base64(const struct test* t) { int r = EXIT_FAILURE; @@ -124,7 +88,6 @@ FAIL: int main(int argc, const char* argv[]) { testsuite_add_test(test_mkdir, TEST_WANTS_PAKFIRE); - testsuite_add_test(test_path_match, 0); testsuite_add_test(test_base64, 0); return testsuite_run(argc, argv); -- 2.39.5