From 3b703fe269a4a34f1b5ad1c3ce219c8c407e6fe1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 17 Aug 2022 06:43:37 +0900 Subject: [PATCH] path-util: introduce path_glob_can_match() --- src/basic/path-util.c | 61 +++++++++++++++++++++++++++++++++++++++++++ src/basic/path-util.h | 2 ++ 2 files changed, 63 insertions(+) diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 13d71ed..bec930f 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include +#include #include #include #include @@ -1395,3 +1396,63 @@ bool prefixed_path_strv_contains(char **l, const char *path) { return false; } + +int path_glob_can_match(const char *pattern, const char *prefix, char **ret) { + assert(pattern); + assert(prefix); + + for (const char *a = pattern, *b = prefix;;) { + _cleanup_free_ char *g = NULL, *h = NULL; + const char *p, *q; + int r, s; + + r = path_find_first_component(&a, /* accept_dot_dot = */ false, &p); + if (r < 0) + return r; + + s = path_find_first_component(&b, /* accept_dot_dot = */ false, &q); + if (s < 0) + return s; + + if (s == 0) { + /* The pattern matches the prefix. */ + if (ret) { + char *t; + + t = path_join(prefix, p); + if (!t) + return -ENOMEM; + + *ret = t; + } + return true; + } + + if (r == 0) + break; + + if (r == s && strneq(p, q, r)) + continue; /* common component. Check next. */ + + g = strndup(p, r); + if (!g) + return -ENOMEM; + + if (!string_is_glob(g)) + break; + + /* We found a glob component. Check if the glob pattern matches the prefix component. */ + + h = strndup(q, s); + if (!h) + return -ENOMEM; + + if (fnmatch(g, h, 0) != 0) + break; + } + + /* The pattern does not match the prefix. */ + if (ret) + *ret = NULL; + return false; +} diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 26e7362..c374a77 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -202,3 +202,5 @@ static inline const char *empty_to_root(const char *path) { bool path_strv_contains(char **l, const char *path); bool prefixed_path_strv_contains(char **l, const char *path); + +int path_glob_can_match(const char *pattern, const char *prefix, char **ret); -- 2.33.0