diff options
-rw-r--r-- | dir.c | 2 | ||||
-rwxr-xr-x | t/t3070-wildmatch.sh | 27 | ||||
-rw-r--r-- | test-wildmatch.c | 6 | ||||
-rw-r--r-- | wildmatch.c | 13 | ||||
-rw-r--r-- | wildmatch.h | 1 |
5 files changed, 42 insertions, 7 deletions
@@ -595,7 +595,7 @@ int match_pathname(const char *pathname, int pathlen, } return wildmatch(pattern, name, - ignore_case ? WM_CASEFOLD : 0, + WM_PATHNAME | (ignore_case ? WM_CASEFOLD : 0), NULL) == 0; } diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index af54c83111..5c9601a0c8 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -29,6 +29,18 @@ match() { fi } +pathmatch() { + if [ $1 = 1 ]; then + test_expect_success "pathmatch: match '$2' '$3'" " + test-wildmatch pathmatch '$2' '$3' + " + else + test_expect_success "pathmatch: no match '$2' '$3'" " + ! test-wildmatch pathmatch '$2' '$3' + " + fi +} + # Basic wildmat features match 1 1 foo foo match 0 0 foo bar @@ -192,4 +204,19 @@ match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/ match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t' match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t' +pathmatch 1 foo foo +pathmatch 0 foo fo +pathmatch 1 foo/bar foo/bar +pathmatch 1 foo/bar 'foo/*' +pathmatch 1 foo/bba/arr 'foo/*' +pathmatch 1 foo/bba/arr 'foo/**' +pathmatch 1 foo/bba/arr 'foo*' +pathmatch 1 foo/bba/arr 'foo**' +pathmatch 1 foo/bba/arr 'foo/*arr' +pathmatch 1 foo/bba/arr 'foo/**arr' +pathmatch 0 foo/bba/arr 'foo/*z' +pathmatch 0 foo/bba/arr 'foo/**z' +pathmatch 1 foo/bar 'foo?bar' +pathmatch 1 foo/bar 'foo[/]bar' + test_done diff --git a/test-wildmatch.c b/test-wildmatch.c index 4bb23b4c92..a5f4833770 100644 --- a/test-wildmatch.c +++ b/test-wildmatch.c @@ -12,9 +12,11 @@ int main(int argc, char **argv) argv[i] += 3; } if (!strcmp(argv[1], "wildmatch")) - return !!wildmatch(argv[3], argv[2], 0, NULL); + return !!wildmatch(argv[3], argv[2], WM_PATHNAME, NULL); else if (!strcmp(argv[1], "iwildmatch")) - return !!wildmatch(argv[3], argv[2], WM_CASEFOLD, NULL); + return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD, NULL); + else if (!strcmp(argv[1], "pathmatch")) + return !!wildmatch(argv[3], argv[2], 0, NULL); else if (!strcmp(argv[1], "fnmatch")) return !!fnmatch(argv[3], argv[2], FNM_PATHNAME); else diff --git a/wildmatch.c b/wildmatch.c index 1b5bbacf1a..536470b794 100644 --- a/wildmatch.c +++ b/wildmatch.c @@ -78,14 +78,17 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) continue; case '?': /* Match anything but '/'. */ - if (t_ch == '/') + if ((flags & WM_PATHNAME) && t_ch == '/') return WM_NOMATCH; continue; case '*': if (*++p == '*') { const uchar *prev_p = p - 2; while (*++p == '*') {} - if ((prev_p < pattern || *prev_p == '/') && + if (!(flags & WM_PATHNAME)) + /* without WM_PATHNAME, '*' == '**' */ + match_slash = 1; + else if ((prev_p < pattern || *prev_p == '/') && (*p == '\0' || *p == '/' || (p[0] == '\\' && p[1] == '/'))) { /* @@ -104,7 +107,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) } else return WM_ABORT_MALFORMED; } else - match_slash = 0; + /* without WM_PATHNAME, '*' == '**' */ + match_slash = flags & WM_PATHNAME ? 0 : 1; if (*p == '\0') { /* Trailing "**" matches everything. Trailing "*" matches * only if there are no more slash characters. */ @@ -215,7 +219,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) } else if (t_ch == p_ch) matched = 1; } while (prev_ch = p_ch, (p_ch = *++p) != ']'); - if (matched == negated || t_ch == '/') + if (matched == negated || + ((flags & WM_PATHNAME) && t_ch == '/')) return WM_NOMATCH; continue; } diff --git a/wildmatch.h b/wildmatch.h index 1c814fd5ff..4090c8f4bb 100644 --- a/wildmatch.h +++ b/wildmatch.h @@ -2,6 +2,7 @@ #define WILDMATCH_H #define WM_CASEFOLD 1 +#define WM_PATHNAME 2 #define WM_ABORT_MALFORMED 2 #define WM_NOMATCH 1 |