char* pakfire_unquote_in_place(char* s);
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);
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;
+
+ // 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++) {
+ switch (*s) {
+ // Found slash!
+ case '/':
+ if (stars == 1)
+ return pakfire_path_match(p, s);
+
+ // Otherwise fall through
+
+ // Read as many characters as possible
+ default:
+ continue;
+ }
+ }
+
+ // 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)
+ 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;
+ }
+ }
+
+ // We reached the end of the string and all characters matched
+ return 1;
+}
+
time_t pakfire_path_age(const char* path) {
struct stat st;
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);
+
+ return EXIT_SUCCESS;
+
+FAIL:
+ return EXIT_FAILURE;
+}
+
int main(int argc, const char* argv[]) {
testsuite_add_test(test_basename);
testsuite_add_test(test_dirname);
testsuite_add_test(test_mkdir);
+ testsuite_add_test(test_path_match);
return testsuite_run(argc, argv);
}