]>
Commit | Line | Data |
---|---|---|
1f2f436a A |
1 | --- fnmatch.c.orig 2011-02-17 17:11:04.000000000 -0800 |
2 | +++ fnmatch.c 2011-02-18 12:00:31.000000000 -0800 | |
3 | @@ -36,6 +36,8 @@ static char sccsid[] = "@(#)fnmatch.c 8. | |
3d9156a7 | 4 | #include <sys/cdefs.h> |
1f2f436a | 5 | __FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.19 2010/04/16 22:29:24 jilles Exp $"); |
3d9156a7 A |
6 | |
7 | +#include "xlocale_private.h" | |
8 | + | |
9 | /* | |
10 | * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. | |
11 | * Compares a filename or pathname to a pattern. | |
1f2f436a | 12 | @@ -62,13 +64,16 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/fnm |
224c7076 A |
13 | |
14 | #define EOS '\0' | |
15 | ||
224c7076 | 16 | +#define RETURN_ERROR 2 /* neither 0 or FNM_NOMATCH */ |
224c7076 | 17 | #define RANGE_MATCH 1 |
3d9156a7 A |
18 | #define RANGE_NOMATCH 0 |
19 | #define RANGE_ERROR (-1) | |
20 | ||
21 | -static int rangematch(const char *, wchar_t, int, char **, mbstate_t *); | |
1f2f436a A |
22 | +#define RECURSION_MAX 64 |
23 | + | |
224c7076 | 24 | +__private_extern__ int rangematch(const char *, wchar_t, const char *, int, char **, char **, mbstate_t *, mbstate_t *, locale_t); |
1f2f436a A |
25 | static int fnmatch1(const char *, const char *, const char *, int, mbstate_t, |
26 | - mbstate_t); | |
27 | + mbstate_t, locale_t, int); | |
3d9156a7 A |
28 | |
29 | int | |
30 | fnmatch(pattern, string, flags) | |
1f2f436a A |
31 | @@ -76,27 +81,38 @@ fnmatch(pattern, string, flags) |
32 | int flags; | |
3d9156a7 A |
33 | { |
34 | static const mbstate_t initial; | |
1f2f436a A |
35 | - |
36 | - return (fnmatch1(pattern, string, string, flags, initial, initial)); | |
37 | +#if __DARWIN_UNIX03 | |
38 | + return (fnmatch1(pattern, string, string, flags, initial, initial, __current_locale(), RECURSION_MAX)); | |
39 | +#else /* !__DARWIN_UNIX03 */ | |
40 | + return (fnmatch1(pattern, string, string, flags, initial, initial, __current_locale(), RECURSION_MAX) != 0 ? FNM_NOMATCH : 0); | |
41 | +#endif /* __DARWIN_UNIX03 */ | |
3d9156a7 A |
42 | } |
43 | ||
44 | static int | |
1f2f436a A |
45 | -fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs) |
46 | +fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs, loc, recursion) | |
47 | const char *pattern, *string, *stringstart; | |
3d9156a7 A |
48 | int flags; |
49 | mbstate_t patmbs, strmbs; | |
50 | + locale_t loc; | |
1f2f436a | 51 | + int recursion; |
3d9156a7 | 52 | { |
224c7076 A |
53 | - char *newp; |
54 | + char *newp, *news; | |
55 | char c; | |
56 | wchar_t pc, sc; | |
3d9156a7 A |
57 | size_t pclen, sclen; |
58 | ||
1f2f436a A |
59 | + if (recursion-- <= 0) |
60 | + return RETURN_ERROR; | |
61 | for (;;) { | |
3d9156a7 A |
62 | - pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs); |
63 | + pclen = mbrtowc_l(&pc, pattern, MB_LEN_MAX, &patmbs, loc); | |
64 | if (pclen == (size_t)-1 || pclen == (size_t)-2) | |
224c7076 A |
65 | +#if __DARWIN_UNIX03 |
66 | + return (RETURN_ERROR); | |
67 | +#else /* !__DARWIN_UNIX03 */ | |
3d9156a7 | 68 | return (FNM_NOMATCH); |
224c7076 | 69 | +#endif /* __DARWIN_UNIX03 */ |
3d9156a7 A |
70 | pattern += pclen; |
71 | - sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs); | |
72 | + sclen = mbrtowc_l(&sc, string, MB_LEN_MAX, &strmbs, loc); | |
73 | if (sclen == (size_t)-1 || sclen == (size_t)-2) { | |
74 | sc = (unsigned char)*string; | |
75 | sclen = 1; | |
1f2f436a A |
76 | @@ -144,12 +160,13 @@ fnmatch1(pattern, string, stringstart, f |
77 | } | |
78 | ||
3d9156a7 | 79 | /* General case, use recursion. */ |
1f2f436a | 80 | + int ret; |
3d9156a7 | 81 | while (sc != EOS) { |
1f2f436a A |
82 | - if (!fnmatch1(pattern, string, stringstart, |
83 | - flags, patmbs, strmbs)) | |
84 | - return (0); | |
3d9156a7 A |
85 | - sclen = mbrtowc(&sc, string, MB_LEN_MAX, |
86 | - &strmbs); | |
1f2f436a A |
87 | + if ((ret = fnmatch1(pattern, string, stringstart, |
88 | + flags, patmbs, strmbs, loc, recursion)) != FNM_NOMATCH) | |
89 | + return (ret); | |
3d9156a7 A |
90 | + sclen = mbrtowc_l(&sc, string, MB_LEN_MAX, |
91 | + &strmbs, loc); | |
92 | if (sclen == (size_t)-1 || | |
93 | sclen == (size_t)-2) { | |
94 | sc = (unsigned char)*string; | |
1f2f436a | 95 | @@ -171,35 +188,45 @@ fnmatch1(pattern, string, stringstart, f |
224c7076 | 96 | ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) |
3d9156a7 A |
97 | return (FNM_NOMATCH); |
98 | ||
224c7076 | 99 | - switch (rangematch(pattern, sc, flags, &newp, |
3d9156a7 | 100 | - &patmbs)) { |
224c7076 A |
101 | + switch (rangematch(pattern, sc, string + sclen, flags, |
102 | + &newp, &news, &patmbs, &strmbs, loc)) { | |
3d9156a7 | 103 | case RANGE_ERROR: |
224c7076 A |
104 | +#if __DARWIN_UNIX03 |
105 | + return (RETURN_ERROR); | |
106 | +#else /* !__DARWIN_UNIX03 */ | |
3d9156a7 | 107 | goto norm; |
224c7076 | 108 | +#endif /* __DARWIN_UNIX03 */ |
3d9156a7 | 109 | case RANGE_MATCH: |
224c7076 A |
110 | pattern = newp; |
111 | + string = news; | |
112 | break; | |
113 | case RANGE_NOMATCH: | |
114 | return (FNM_NOMATCH); | |
115 | } | |
116 | - string += sclen; | |
3d9156a7 A |
117 | break; |
118 | case '\\': | |
119 | if (!(flags & FNM_NOESCAPE)) { | |
120 | - pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, | |
121 | - &patmbs); | |
122 | + pclen = mbrtowc_l(&pc, pattern, MB_LEN_MAX, | |
123 | + &patmbs, loc); | |
124 | if (pclen == (size_t)-1 || pclen == (size_t)-2) | |
224c7076 A |
125 | +#if __DARWIN_UNIX03 |
126 | + return (RETURN_ERROR); | |
127 | +#else /* !__DARWIN_UNIX03 */ | |
3d9156a7 | 128 | return (FNM_NOMATCH); |
224c7076 | 129 | +#endif /* __DARWIN_UNIX03 */ |
3d9156a7 | 130 | if (pclen == 0) |
224c7076 A |
131 | pc = '\\'; |
132 | pattern += pclen; | |
133 | } | |
134 | /* FALLTHROUGH */ | |
135 | default: | |
136 | +#if !__DARWIN_UNIX03 | |
137 | norm: | |
138 | +#endif /* !__DARWIN_UNIX03 */ | |
3d9156a7 A |
139 | if (pc == sc) |
140 | ; | |
141 | else if ((flags & FNM_CASEFOLD) && | |
142 | - (towlower(pc) == towlower(sc))) | |
143 | + (towlower_l(pc, loc) == towlower_l(sc, loc))) | |
144 | ; | |
145 | else | |
146 | return (FNM_NOMATCH); | |
1f2f436a | 147 | @@ -210,18 +237,22 @@ fnmatch1(pattern, string, stringstart, f |
224c7076 | 148 | /* NOTREACHED */ |
3d9156a7 A |
149 | } |
150 | ||
224c7076 | 151 | -static int |
3d9156a7 | 152 | -rangematch(pattern, test, flags, newp, patmbs) |
224c7076 A |
153 | - const char *pattern; |
154 | +#ifndef BUILDING_VARIANT | |
155 | +__private_extern__ int | |
156 | +rangematch(pattern, test, string, flags, newp, news, patmbs, strmbs, loc) | |
157 | + const char *pattern, *string; | |
3d9156a7 A |
158 | wchar_t test; |
159 | int flags; | |
224c7076 A |
160 | - char **newp; |
161 | - mbstate_t *patmbs; | |
162 | + char **newp, **news; | |
163 | + mbstate_t *patmbs, *strmbs; | |
3d9156a7 A |
164 | + locale_t loc; |
165 | { | |
224c7076 A |
166 | - int negate, ok; |
167 | + int negate, ok, special; | |
3d9156a7 | 168 | wchar_t c, c2; |
224c7076 A |
169 | - size_t pclen; |
170 | - const char *origpat; | |
171 | + wchar_t buf[STR_LEN]; /* STR_LEN defined in collate.h */ | |
172 | + size_t pclen, sclen, len; | |
173 | + const char *origpat, *cp, *savestring; | |
174 | + mbstate_t save; | |
175 | ||
176 | /* | |
177 | * A bracket expression starting with an unquoted circumflex | |
1f2f436a | 178 | @@ -234,7 +265,7 @@ rangematch(pattern, test, flags, newp, p |
3d9156a7 A |
179 | ++pattern; |
180 | ||
181 | if (flags & FNM_CASEFOLD) | |
182 | - test = towlower(test); | |
183 | + test = towlower_l(test, loc); | |
184 | ||
185 | /* | |
186 | * A right bracket shall lose its special meaning and represent | |
1f2f436a | 187 | @@ -244,8 +275,8 @@ rangematch(pattern, test, flags, newp, p |
224c7076 A |
188 | ok = 0; |
189 | origpat = pattern; | |
190 | for (;;) { | |
191 | + c = 0; | |
192 | if (*pattern == ']' && pattern > origpat) { | |
193 | - pattern++; | |
194 | break; | |
195 | } else if (*pattern == '\0') { | |
196 | return (RANGE_ERROR); | |
1f2f436a | 197 | @@ -253,39 +284,188 @@ rangematch(pattern, test, flags, newp, p |
3d9156a7 A |
198 | return (RANGE_NOMATCH); |
199 | } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE)) | |
200 | pattern++; | |
201 | - pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs); | |
224c7076 A |
202 | - if (pclen == (size_t)-1 || pclen == (size_t)-2) |
203 | - return (RANGE_NOMATCH); | |
204 | - pattern += pclen; | |
205 | + else if (*pattern == '[' && ((special = *(pattern + 1)) == '.' || special == '=' || special == ':')) { | |
206 | + cp = (pattern += 2); | |
207 | + while(cp = strchr(cp, special)) { | |
208 | + if (*(cp + 1) == ']') | |
209 | + break; | |
210 | + cp++; | |
211 | + } | |
212 | + if (!cp) | |
213 | + return (RANGE_ERROR); | |
214 | + if (special == '.') { | |
215 | +treat_like_collating_symbol: | |
216 | + len = __collate_collating_symbol(buf, STR_LEN, pattern, cp - pattern, patmbs, loc); | |
217 | + if (len == (size_t)-1 || len == 0) | |
218 | + return (RANGE_ERROR); | |
219 | + pattern = cp + 2; | |
220 | + if (len > 1) { | |
221 | + wchar_t *wp, sc; | |
222 | + /* no multi-character collation symbols as start of range */ | |
223 | + if (*(cp + 2) == '-' && *(cp + 3) != EOS | |
224 | + && *(cp + 3) != ']') | |
225 | + return (RANGE_ERROR); | |
226 | + wp = buf; | |
227 | + if (test != *wp++) | |
228 | + continue; | |
229 | + if (len == 1) { | |
230 | + ok = 1; | |
231 | + break; | |
232 | + } | |
233 | + memcpy(&save, strmbs, sizeof(save)); | |
234 | + savestring = string; | |
235 | + while (--len > 0) { | |
236 | + sclen = mbrtowc_l(&sc, string, MB_LEN_MAX, strmbs, loc); | |
237 | + if (sclen == (size_t)-1 || sclen == (size_t)-2) { | |
238 | + sc = (unsigned char)*string; | |
239 | + sclen = 1; | |
240 | + memset(&strmbs, 0, sizeof(strmbs)); | |
241 | + } | |
242 | + if (sc != *wp++) { | |
243 | + memcpy(strmbs, &save, sizeof(save)); | |
244 | + string = savestring; | |
245 | + break; | |
246 | + } | |
247 | + string += sclen; | |
248 | + } | |
249 | + if (len == 0) { | |
250 | + ok = 1; | |
251 | + break; | |
252 | + } | |
253 | + continue; /* no match */ | |
254 | + } | |
255 | + c = *buf; | |
256 | + } else if (special == '=') { | |
257 | + int ec; | |
258 | + memcpy(&save, patmbs, sizeof(save)); | |
259 | + ec = __collate_equiv_class(pattern, cp - pattern, patmbs, loc); | |
260 | + if (ec < 0) | |
261 | + return (RANGE_ERROR); | |
262 | + if (ec == 0) { | |
263 | + memcpy(patmbs, &save, sizeof(save)); | |
264 | + goto treat_like_collating_symbol; | |
265 | + } | |
266 | + pattern = cp + 2; | |
267 | + /* no equivalence classes as start of range */ | |
268 | + if (*(cp + 2) == '-' && *(cp + 3) != EOS && | |
269 | + *(cp + 3) != ']') | |
270 | + return (RANGE_ERROR); | |
271 | + len = __collate_equiv_match(ec, NULL, 0, test, string, strlen(string), strmbs, &sclen, loc); | |
272 | + if (len < 0) | |
273 | + return (RANGE_ERROR); | |
274 | + if (len > 0) { | |
275 | + ok = 1; | |
276 | + string += sclen; | |
277 | + break; | |
278 | + } | |
279 | + continue; | |
280 | + } else { /* special == ':' */ | |
281 | + wctype_t charclass; | |
282 | + char name[CHARCLASS_NAME_MAX + 1]; | |
283 | + /* no character classes as start of range */ | |
284 | + if (*(cp + 2) == '-' && *(cp + 3) != EOS && | |
285 | + *(cp + 3) != ']') | |
286 | + return (RANGE_ERROR); | |
287 | + /* assume character class names are ascii */ | |
288 | + if (cp - pattern > CHARCLASS_NAME_MAX) | |
289 | + return (RANGE_ERROR); | |
290 | + strlcpy(name, pattern, cp - pattern + 1); | |
291 | + pattern = cp + 2; | |
292 | + if ((charclass = wctype(name)) == 0) | |
293 | + return (RANGE_ERROR); | |
294 | + if (iswctype_l(test, charclass, loc)) { | |
295 | + ok = 1; | |
296 | + break; | |
297 | + } | |
298 | + continue; | |
299 | + } | |
300 | + } | |
301 | + if (!c) { | |
302 | + pclen = mbrtowc_l(&c, pattern, MB_LEN_MAX, patmbs, loc); | |
303 | + if (pclen == (size_t)-1 || pclen == (size_t)-2) | |
304 | + return (RANGE_ERROR); | |
305 | + pattern += pclen; | |
306 | + } | |
3d9156a7 A |
307 | |
308 | if (flags & FNM_CASEFOLD) | |
309 | - c = towlower(c); | |
310 | + c = towlower_l(c, loc); | |
311 | ||
312 | if (*pattern == '-' && *(pattern + 1) != EOS && | |
313 | *(pattern + 1) != ']') { | |
314 | if (*++pattern == '\\' && !(flags & FNM_NOESCAPE)) | |
315 | if (*pattern != EOS) | |
316 | pattern++; | |
317 | - pclen = mbrtowc(&c2, pattern, MB_LEN_MAX, patmbs); | |
318 | + pclen = mbrtowc_l(&c2, pattern, MB_LEN_MAX, patmbs, loc); | |
319 | if (pclen == (size_t)-1 || pclen == (size_t)-2) | |
224c7076 A |
320 | - return (RANGE_NOMATCH); |
321 | + return (RANGE_ERROR); | |
3d9156a7 | 322 | pattern += pclen; |
224c7076 | 323 | if (c2 == EOS) |
3d9156a7 A |
324 | return (RANGE_ERROR); |
325 | ||
224c7076 A |
326 | + if (c2 == '[' && (special = *pattern) == '.' || special == '=' || special == ':') { |
327 | + /* no equivalence classes or character classes as end of range */ | |
328 | + if (special == '=' || special == ':') | |
329 | + return (RANGE_ERROR); | |
330 | + cp = ++pattern; | |
331 | + while(cp = strchr(cp, special)) { | |
332 | + if (*(cp + 1) == ']') | |
333 | + break; | |
334 | + cp++; | |
335 | + } | |
336 | + if (!cp) | |
337 | + return (RANGE_ERROR); | |
338 | + len = __collate_collating_symbol(buf, STR_LEN, pattern, cp - pattern, patmbs, loc); | |
339 | + /* no multi-character collation symbols as end of range */ | |
340 | + if (len != 1) | |
341 | + return (RANGE_ERROR); | |
342 | + pattern = cp + 2; | |
343 | + c2 = *buf; | |
344 | + } | |
345 | + | |
3d9156a7 A |
346 | if (flags & FNM_CASEFOLD) |
347 | - c2 = towlower(c2); | |
348 | + c2 = towlower_l(c2, loc); | |
349 | ||
350 | - if (__collate_load_error ? | |
351 | + if (loc->__collate_load_error ? | |
352 | c <= test && test <= c2 : | |
353 | - __collate_range_cmp(c, test) <= 0 | |
354 | - && __collate_range_cmp(test, c2) <= 0 | |
224c7076 | 355 | - ) |
3d9156a7 A |
356 | + __collate_range_cmp(c, test, loc) <= 0 |
357 | + && __collate_range_cmp(test, c2, loc) <= 0 | |
224c7076 | 358 | + ) { |
3d9156a7 | 359 | ok = 1; |
224c7076 A |
360 | - } else if (c == test) |
361 | + break; | |
362 | + } | |
363 | + } else if (c == test) { | |
364 | ok = 1; | |
365 | + break; | |
366 | + } | |
367 | } | |
368 | + /* go to end of bracket expression */ | |
369 | + special = 0; | |
370 | + while(*pattern != ']') { | |
371 | + if (*pattern == 0) | |
372 | + return (RANGE_ERROR); | |
373 | + if (*pattern == special) { | |
374 | + if (*++pattern == ']') { | |
375 | + special = 0; | |
376 | + pattern++; | |
377 | + } | |
378 | + continue; | |
379 | + } | |
380 | + if (!special && *pattern == '[') { | |
381 | + special = *++pattern; | |
382 | + if (special != '.' && special != '=' && special != ':') | |
383 | + special = 0; | |
384 | + else | |
385 | + pattern++; | |
386 | + continue; | |
387 | + } | |
388 | + pclen = mbrtowc_l(&c, pattern, MB_LEN_MAX, patmbs, loc); | |
389 | + if (pclen == (size_t)-1 || pclen == (size_t)-2) | |
390 | + return (RANGE_ERROR); | |
391 | + pattern += pclen; | |
392 | + } | |
393 | ||
394 | - *newp = (char *)pattern; | |
395 | + *newp = (char *)++pattern; | |
396 | + *news = (char *)string; | |
397 | return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); | |
398 | } | |
399 | +#endif /* BUILDING_VARIANT */ |