diff --git a/cmdline/elem.c b/cmdline/elem.c index 4b18fed1..3a4be8d1 100644 --- a/cmdline/elem.c +++ b/cmdline/elem.c @@ -186,27 +186,35 @@ static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** path += strlen(filter->root); } - /* match dirs with dirs and files with files */ - if (filter->is_dir && !is_dir) - return 0; + /* if the filter is for files, it doesn't applies to directories */ if (!filter->is_dir && is_dir) return 0; + /* + * If the filter is for directories, it should be applied to all files inside + * that directory. + * + * This is done allowing a partial matching as far it ends at a directory separator + */ + int match_sub = 0; + if (filter->is_dir && !is_dir) + match_sub = 1; + int ret = 0; if (filter->is_abs) { /* skip initial slash, as always missing in the path */ - if (wnmatch(filter->pattern + 1, path) == 0) + if (wnmatch_sub(filter->pattern + 1, path, match_sub) == 0) ret = filter->direction; } else { /* the path is relative, first try to match from the root */ - if (wnmatch(filter->pattern, path) == 0) { + if (wnmatch_sub(filter->pattern, path, match_sub) == 0) { ret = filter->direction; } else { /* then try to match after all the / presents */ char* slash = strchr(path, '/'); while (slash) { - if (wnmatch(filter->pattern, slash + 1) == 0) { + if (wnmatch_sub(filter->pattern, slash + 1, match_sub) == 0) { ret = filter->direction; break; } diff --git a/cmdline/support.c b/cmdline/support.c index 94a6cc1c..e30b4cb4 100644 --- a/cmdline/support.c +++ b/cmdline/support.c @@ -2541,7 +2541,7 @@ static const char* match_class(const char* p, char t) return p; } -int wnmatch(const char* p, const char* t) +int wnmatch_sub(const char* p, const char* t, int match_sub) { char p1 = 0; /* previous char */ while (*p) { @@ -2582,20 +2582,20 @@ int wnmatch(const char* p, const char* t) */ if (*p == '/' && (p1 == 0 || p1 == '/')) { /* try reducing to nothing */ - if (wnmatch(p + 1, t) == 0) + if (wnmatch_sub(p + 1, t, match_sub) == 0) return 0; /* otherwise / should match in the text */ } /* try matching with 0 or more characters */ while (*t) { - if (wnmatch(p, t) == 0) + if (wnmatch_sub(p, t, match_sub) == 0) return 0; ++t; } /* try matching at the end */ - return wnmatch(p, t); + return wnmatch_sub(p, t, match_sub); } } else { /* skip the * */ @@ -2611,13 +2611,13 @@ int wnmatch(const char* p, const char* t) /* try matching with 0 or more characters */ while (*t && *t != '/') { - if (wnmatch(p, t) == 0) + if (wnmatch_sub(p, t, match_sub) == 0) return 0; ++t; } /* try matching at the end */ - return wnmatch(p, t); + return wnmatch_sub(p, t, match_sub); case '[' : /* character class */ if (*t == 0 || *t == '/') @@ -2640,7 +2640,13 @@ int wnmatch(const char* p, const char* t) p1 = p0; } - /* match successful if we've consumed all text */ - return *t != 0; + /* if we match sub directory */ + if (match_sub) { + /* match successfully only if we are at a directory border */ + return *t != '/'; + } else { + /* match successfully if we've consumed all text */ + return *t != 0; + } } diff --git a/cmdline/support.h b/cmdline/support.h index 69fb90bd..67cc2da1 100644 --- a/cmdline/support.h +++ b/cmdline/support.h @@ -523,14 +523,24 @@ void thread_yield(void); /* * Wild match function. * + * If match_sub is !=0, it matches sub directory. Specifically it matches if the + * string "t" is not fully consumed and the next character to consume is a /. + * * - ? matches any single character except / * - * matches any sequence of characters except / * - ** (nearby a /) matches everything including / * - ** (not near a /) like * - * - ##/ reduces to nothing in addition to the normal matching of ** (using # instead of * to mess the C comment) + * - ##/ reduces to nothing in addition to the normal matching of ** (using # instead of * to not mess the C comment) * - [...] matches character classes with support for ranges and negation lile [!...] or [^...], except / + * + * \return 0 if it matches */ -int wnmatch(const char* p, const char* t); +int wnmatch_sub(const char* p, const char* t, int match_sub); + +static inline int wnmatch(const char* p, const char* t) +{ + return wnmatch_sub(p, t, 0); +} #endif