• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define _GNU_SOURCE 1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <fnmatch.h>
5 #include <unistd.h>
6 #include "test.h"
7 
8 /* adapted from dietlibc's test-newfnmatch.c */
9 
10 /* xlat / printflags adapted from http://www.liacs.nl/~wichert/strace/ */
11 #define FLAG(f) { f, #f }
12 
13 struct xlat {
14 	int val;
15 	char *str;
16 } fnmatch_flags[] = {
17 	FLAG(FNM_NOESCAPE),
18 	FLAG(FNM_PATHNAME),
19 	FLAG(FNM_PERIOD),
20 #ifdef FNM_CASEFOLD
21 	FLAG(FNM_CASEFOLD),
22 #endif
23 	{0, NULL},
24 };
25 
flagstr(const struct xlat * map,int flags)26 static char *flagstr(const struct xlat *map, int flags)
27 {
28 	static char buf[1000];
29 	char *sep;
30 	int n;
31 
32 	if (!flags) {
33 		sprintf(buf, "0");
34 		return buf;
35 	}
36 	n = 0;
37 	sep = "";
38 	for (; map->str; map++) {
39 		if (map->val && (flags & map->val) == map->val) {
40 			n += sprintf(buf+n, "%s%s", sep, map->str);
41 			sep = "|";
42 			flags &= ~(map->val);
43 		}
44 	}
45 	if (flags)
46 		sprintf(buf, "%sunknown=%#x", sep, flags);
47 	return buf;
48 }
49 
50 /* tests harness adapted from glibc testfnm.c */
51 struct {
52 	const char *pattern;
53 	const char *string;
54 	int flags;
55 	int expected;
56 } tests[] = {
57 	/* begin dietlibc tests */
58 	{ "*.c", "foo.c", 0, 0 },
59 	{ "*.c", ".c", 0, 0 },
60 	{ "*.a", "foo.c", 0, FNM_NOMATCH },
61 	{ "*.c", ".foo.c", 0, 0 },
62 	{ "*.c", ".foo.c", FNM_PERIOD, FNM_NOMATCH },
63 	{ "*.c", "foo.c", FNM_PERIOD, 0 },
64 	{ "a\\*.c", "a*.c", FNM_NOESCAPE, FNM_NOMATCH },
65 	{ "a\\*.c", "ax.c", 0, FNM_NOMATCH },
66 	{ "a[xy].c", "ax.c", 0, 0 },
67 	{ "a[!y].c", "ax.c", 0, 0 },
68 	{ "a[a/z]*.c", "a/x.c", FNM_PATHNAME, FNM_NOMATCH },
69 	{ "a/*.c", "a/x.c", FNM_PATHNAME, 0 },
70 	{ "a*.c", "a/x.c", FNM_PATHNAME, FNM_NOMATCH },
71 	{ "*/foo", "/foo", FNM_PATHNAME, 0 },
72 	{ "-O[01]", "-O1", 0, 0 },
73 	{ "[[?*\\]", "\\", 0, 0 },
74 	{ "[]?*\\]", "]", 0, 0 },
75 	/* initial right-bracket tests */
76 	{ "[!]a-]", "b", 0, 0 },
77 	{ "[]-_]", "^", 0, 0 }, /* range: ']', '^', '_' */
78 	{ "[!]-_]", "X", 0, 0 },
79 	{ "??", "-", 0, FNM_NOMATCH },
80 	/* begin glibc tests */
81 	{ "*LIB*", "lib", FNM_PERIOD, FNM_NOMATCH },
82 	{ "a[/]b", "a/b", 0, 0 },
83 	{ "a[/]b", "a/b", FNM_PATHNAME, FNM_NOMATCH },
84 	{ "[a-z]/[a-z]", "a/b", 0, 0 },
85 	{ "*", "a/b", FNM_PATHNAME, FNM_NOMATCH },
86 	{ "*[/]b", "a/b", FNM_PATHNAME, FNM_NOMATCH },
87 	{ "*[b]", "a/b", FNM_PATHNAME, FNM_NOMATCH },
88 	{ "[*]/b", "a/b", 0, FNM_NOMATCH },
89 	{ "[*]/b", "*/b", 0, 0 },
90 	{ "[?]/b", "a/b", 0, FNM_NOMATCH },
91 	{ "[?]/b", "?/b", 0, 0 },
92 	{ "[[a]/b", "a/b", 0, 0 },
93 	{ "[[a]/b", "[/b", 0, 0 },
94 	{ "\\*/b", "a/b", 0, FNM_NOMATCH },
95 	{ "\\*/b", "*/b", 0, 0 },
96 	{ "\\?/b", "a/b", 0, FNM_NOMATCH },
97 	{ "\\?/b", "?/b", 0, 0 },
98 	{ "[/b", "[/b", 0, 0 },
99 	{ "\\[/b", "[/b", 0, 0 },
100 	{ "??""/b", "aa/b", 0, 0 },
101 	{ "???b", "aa/b", 0, 0 },
102 	{ "???b", "aa/b", FNM_PATHNAME, FNM_NOMATCH },
103 	{ "?a/b", ".a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
104 	{ "a/?b", "a/.b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
105 	{ "*a/b", ".a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
106 	{ "a/*b", "a/.b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
107 	{ "[.]a/b", ".a/b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
108 	{ "a/[.]b", "a/.b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
109 	{ "*/?", "a/b", FNM_PATHNAME|FNM_PERIOD, 0 },
110 	{ "?/*", "a/b", FNM_PATHNAME|FNM_PERIOD, 0 },
111 	{ ".*/?", ".a/b", FNM_PATHNAME|FNM_PERIOD, 0 },
112 	{ "*/.?", "a/.b", FNM_PATHNAME|FNM_PERIOD, 0 },
113 	{ "*/*", "a/.b", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH },
114 	{ "*?*/*", "a/.b", FNM_PERIOD, 0 },
115 	{ "*[.]/b", "a./b", FNM_PATHNAME|FNM_PERIOD, 0 },
116 	{ "*[[:alpha:]]/*[[:alnum:]]", "a/b", FNM_PATHNAME, 0 },
117 	/* These three tests should result in error according to SUSv3.
118 	 * See XCU 2.13.1, XBD 9.3.5, & fnmatch() */
119 	{ "*[![:digit:]]*/[![:d-d]", "a/b", FNM_PATHNAME, -FNM_NOMATCH },
120 	{ "*[![:digit:]]*/[[:d-d]", "a/[", FNM_PATHNAME, -FNM_NOMATCH },
121 	{ "*[![:digit:]]*/[![:d-d]", "a/[", FNM_PATHNAME, -FNM_NOMATCH },
122 	{ "a?b", "a.b", FNM_PATHNAME|FNM_PERIOD, 0 },
123 	{ "a*b", "a.b", FNM_PATHNAME|FNM_PERIOD, 0 },
124 	{ "a[.]b", "a.b", FNM_PATHNAME|FNM_PERIOD, 0 },
125 
126 	/* posix 2008 is unclear about these cases */
127 	{ "\\", "\\", 0, 0 },
128 	{ "\\", "", 0, FNM_NOMATCH },
129 
130 	/* musl bug fixed in da0fcdb8e913ca7cdf8931328f2b37e93309b2c5 */
131 	{ "/", "\0", FNM_PATHNAME, FNM_NOMATCH },
132 	/* musl bug fixed in 6ec82a3b58ee1b873ff0dfad8fa9d41c3d25dcc0 */
133 	{ "\\/", "/", FNM_PATHNAME, 0 },
134 
135 #ifdef FNM_CASEFOLD
136 	{ "a", "A", FNM_CASEFOLD, 0 },
137 	{ "aaAA", "AaAa", FNM_CASEFOLD, 0 },
138 	{ "[a]", "A", FNM_CASEFOLD, 0 },
139 	{ "[!a]", "A", FNM_CASEFOLD, FNM_NOMATCH },
140 	{ "[!A-C]", "b", FNM_CASEFOLD, FNM_NOMATCH },
141 	{ "[!a-c]", "B", FNM_CASEFOLD, FNM_NOMATCH },
142 	{ "[!a-c]", "d", FNM_CASEFOLD, 0 },
143 #endif
144 };
145 
main(void)146 int main(void)
147 {
148 	int i;
149 
150 	for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
151 		int r, x;
152 
153 		r = fnmatch(tests[i].pattern, tests[i].string, tests[i].flags);
154 		x = tests[i].expected;
155 		if (r != x && (r != FNM_NOMATCH || x != -FNM_NOMATCH)) {
156 			t_error("fnmatch(\"%s\", \"%s\", %s) failed, got %d want %d\n",
157 				tests[i].pattern, tests[i].string,
158 				flagstr(fnmatch_flags, tests[i].flags),
159 				r, x);
160 		}
161 	}
162 	return t_status;
163 }
164