mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Fix filter matching of directory specifications
This commit is contained in:
parent
f76e617f70
commit
ea5f8d0f5f
3 changed files with 40 additions and 16 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue