path: root/src
diff options
authorRich Felker <>2013-12-02 02:08:41 -0500
committerRich Felker <>2013-12-02 02:08:41 -0500
commita4e10e304d54c6ac3c12db08774ef74a978a2073 (patch)
tree92a1316b1c521af1044d8524de48a1cc77610d20 /src
parenta2231757044db66a36b9899a56011ae0cbac8d1e (diff)
implement FNM_LEADING_DIR extension flag in fnmatch
previously this flag was defined and accepted as a no-op, possibly breaking some software that uses it. given the choice to remove the definition and possibly break applications that were already working, or simply implement the feature, the latter turned out to be easy enough to make the decision easy. in the case where the FNM_PATHNAME flag is also set, this implementation is clean and essentially optimal. otherwise, it's an inefficient "brute force" implementation. at some point, when cleaning up and refactoring this code, I may add a more direct code path for handling FNM_LEADING_DIR in the non-FNM_PATHNAME case, but at this point my main interest is avoiding introducing new bugs in the code that implements the standard fnmatch features specified by POSIX.
Diffstat (limited to 'src')
1 files changed, 9 insertions, 2 deletions
diff --git a/src/regex/fnmatch.c b/src/regex/fnmatch.c
index 093eb1cc..4df10a3c 100644
--- a/src/regex/fnmatch.c
+++ b/src/regex/fnmatch.c
@@ -288,12 +288,19 @@ int fnmatch(const char *pat, const char *str, int flags)
if (flags & FNM_PATHNAME) for (;;) {
for (s=str; *s && *s!='/'; s++);
for (p=pat; (c=pat_next(p, -1, &inc, flags))!=END && c!='/'; p+=inc);
- if (c!=*s) return FNM_NOMATCH;
+ if (c!=*s && (!*s || !(flags & FNM_LEADING_DIR)))
+ return FNM_NOMATCH;
if (fnmatch_internal(pat, p-pat, str, s-str, flags))
- if (!*s) return 0;
+ if (!c) return 0;
str = s+1;
pat = p+inc;
+ } else if (flags & FNM_LEADING_DIR) {
+ for (s=str; *s; s++) {
+ if (*s != '/') continue;
+ if (!fnmatch_internal(pat, -1, str, s-str, flags))
+ return 0;
+ }
return fnmatch_internal(pat, -1, str, -1, flags);