| #include <stdio.h> |
| #include <stdlib.h> |
| #include <fnmatch.h> |
| #include <unistd.h> |
| #include "test.h" |
| |
| |
| |
| |
| #define FLAG(f) { f, #f } |
| |
| struct xlat { |
| int val; |
| char *str; |
| } fnmatch_flags[] = { |
| FLAG(FNM_NOESCAPE), |
| FLAG(FNM_PATHNAME), |
| FLAG(FNM_PERIOD), |
| {0, NULL}, |
| }; |
| |
| static char *flagstr(const struct xlat *map, int flags) |
| { |
| static char buf[1000]; |
| char *sep; |
| |
| if (!flags) { |
| sprintf(buf, "0"); |
| return buf; |
| } |
| sep = ""; |
| for (; map->str; map++) { |
| if (map->val && (flags & map->val) == map->val) { |
| sprintf(buf, "%s%s", sep, map->str); |
| sep = "|"; |
| flags &= ~(map->val); |
| } |
| } |
| if (flags) |
| sprintf(buf, "%sunknown=%#x", sep, flags); |
| return buf; |
| } |
| |
| |
| struct { |
| const char *pattern; |
| const char *string; |
| int flags; |
| int expected; |
| } tests[] = { |
| |
| { "*.c", "foo.c", 0, 0 }, |
| { "*.c", ".c", 0, 0 }, |
| { "*.a", "foo.c", 0, FNM_NOMATCH }, |
| { "*.c", ".foo.c", 0, 0 }, |
| { "*.c", ".foo.c", FNM_PERIOD, FNM_NOMATCH }, |
| { "*.c", "foo.c", FNM_PERIOD, 0 }, |
| { "a\\*.c", "a*.c", FNM_NOESCAPE, FNM_NOMATCH }, |
| { "a\\*.c", "ax.c", 0, FNM_NOMATCH }, |
| { "a[xy].c", "ax.c", 0, 0 }, |
| { "a[!y].c", "ax.c", 0, 0 }, |
| { "a[a/z]*.c", "a/x.c", FNM_PATHNAME, FNM_NOMATCH }, |
| { "a/*.c", "a/x.c", FNM_PATHNAME, 0 }, |
| { "a*.c", "a/x.c", FNM_PATHNAME, FNM_NOMATCH }, |
| { "*/foo", "/foo", FNM_PATHNAME, 0 }, |
| { "-O[01]", "-O1", 0, 0 }, |
| { "[[?*\\]", "\\", 0, 0 }, |
| { "[]?*\\]", "]", 0, 0 }, |
| |
| { "[!]a-]", "b", 0, 0 }, |
| { "[]-_]", "^", 0, 0 }, |
| { "[!]-_]", "X", 0, 0 }, |
| { "??", "-", 0, FNM_NOMATCH }, |
| |
| { "*LIB*", "lib", FNM_PERIOD, FNM_NOMATCH }, |
| { "a[/]b", "a/b", 0, 0 }, |
| { "a[/]b", "a/b", FNM_PATHNAME, FNM_NOMATCH }, |
| { "[a-z]/[a-z]", "a/b", 0, 0 }, |
| { "*", "a/b", FNM_PATHNAME, FNM_NOMATCH }, |
| { "*[/]b", "a/b", FNM_PATHNAME, FNM_NOMATCH }, |
| { "*[b]", "a/b", FNM_PATHNAME, FNM_NOMATCH }, |
| { "[*]/b", "a/b", 0, FNM_NOMATCH }, |
| { "[*]/b", "*/b", 0, 0 }, |
| { "[?]/b", "a/b", 0, FNM_NOMATCH }, |
| { "[?]/b", "?/b", 0, 0 }, |
| { "[[a]/b", "a/b", 0, 0 }, |
| { "[[a]/b", "[/b", 0, 0 }, |
| { "\\*/b", "a/b", 0, FNM_NOMATCH }, |
| { "\\*/b", "*/b", 0, 0 }, |
| { "\\?/b", "a/b", 0, FNM_NOMATCH }, |
| { "\\?/b", "?/b", 0, 0 }, |
| { "[/b", "[/b", 0, 0 }, |
| { "\\[/b", "[/b", 0, 0 }, |
| { "??""/b", "aa/b", 0, 0 }, |
| { "???b", "aa/b", 0, 0 }, |
| { "???b", "aa/b", FNM_PATHNAME, FNM_NOMATCH }, |
| { "?a/b", ".a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH }, |
| { "a/?b", "a/.b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH }, |
| { "*a/b", ".a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH }, |
| { "a/*b", "a/.b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH }, |
| { "[.]a/b", ".a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH }, |
| { "a/[.]b", "a/.b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH }, |
| { "*/?", "a/b", FNM_PATHNAME|FNM_PERIOD, 0 }, |
| { "?/*", "a/b", FNM_PATHNAME|FNM_PERIOD, 0 }, |
| { ".*/?", ".a/b", FNM_PATHNAME|FNM_PERIOD, 0 }, |
| { "*/.?", "a/.b", FNM_PATHNAME|FNM_PERIOD, 0 }, |
| { "*/*", "a/.b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH }, |
| { "*?*/*", "a/.b", FNM_PERIOD, 0 }, |
| { "*[.]/b", "a./b", FNM_PATHNAME|FNM_PERIOD, 0 }, |
| { "*[[:alpha:]]/*[[:alnum:]]", "a/b", FNM_PATHNAME, 0 }, |
| |
| |
| { "*[![:digit:]]*/[![:d-d]", "a/b", FNM_PATHNAME, -FNM_NOMATCH }, |
| { "*[![:digit:]]*/[[:d-d]", "a/[", FNM_PATHNAME, -FNM_NOMATCH }, |
| { "*[![:digit:]]*/[![:d-d]", "a/[", FNM_PATHNAME, -FNM_NOMATCH }, |
| { "a?b", "a.b", FNM_PATHNAME|FNM_PERIOD, 0 }, |
| { "a*b", "a.b", FNM_PATHNAME|FNM_PERIOD, 0 }, |
| { "a[.]b", "a.b", FNM_PATHNAME|FNM_PERIOD, 0 }, |
| }; |
| |
| int main(void) |
| { |
| int i; |
| |
| for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { |
| int r, x; |
| |
| r = fnmatch(tests[i].pattern, tests[i].string, tests[i].flags); |
| x = tests[i].expected; |
| if (r != x && (r != FNM_NOMATCH || x != -FNM_NOMATCH)) { |
| t_error("fnmatch(\"%s\", \"%s\", %s) failed, got %d want %d\n", |
| tests[i].pattern, tests[i].string, |
| flagstr(fnmatch_flags, tests[i].flags), |
| r, x); |
| } |
| } |
| return t_status; |
| } |