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.
5 __FBSDID("$FreeBSD: src/lib/libc/gen/fnmatch.c,v 1.19 2010/04/16 22:29:24 jilles Exp $");
7 +#include "xlocale_private.h"
10 * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
11 * Compares a filename or pathname to a pattern.
12 @@ -62,13 +64,16 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/fnm
16 +#define RETURN_ERROR 2 /* neither 0 or FNM_NOMATCH */
18 #define RANGE_NOMATCH 0
19 #define RANGE_ERROR (-1)
21 -static int rangematch(const char *, wchar_t, int, char **, mbstate_t *);
22 +#define RECURSION_MAX 64
24 +__private_extern__ int rangematch(const char *, wchar_t, const char *, int, char **, char **, mbstate_t *, mbstate_t *, locale_t);
25 static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
27 + mbstate_t, locale_t, int);
30 fnmatch(pattern, string, flags)
31 @@ -76,27 +81,38 @@ fnmatch(pattern, string, flags)
34 static const mbstate_t initial;
36 - return (fnmatch1(pattern, string, string, flags, initial, initial));
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 */
45 -fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)
46 +fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs, loc, recursion)
47 const char *pattern, *string, *stringstart;
49 mbstate_t patmbs, strmbs;
59 + if (recursion-- <= 0)
60 + return RETURN_ERROR;
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)
66 + return (RETURN_ERROR);
67 +#else /* !__DARWIN_UNIX03 */
69 +#endif /* __DARWIN_UNIX03 */
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;
76 @@ -144,12 +160,13 @@ fnmatch1(pattern, string, stringstart, f
79 /* General case, use recursion. */
82 - if (!fnmatch1(pattern, string, stringstart,
83 - flags, patmbs, strmbs))
85 - sclen = mbrtowc(&sc, string, MB_LEN_MAX,
87 + if ((ret = fnmatch1(pattern, string, stringstart,
88 + flags, patmbs, strmbs, loc, recursion)) != FNM_NOMATCH)
90 + sclen = mbrtowc_l(&sc, string, MB_LEN_MAX,
92 if (sclen == (size_t)-1 ||
93 sclen == (size_t)-2) {
94 sc = (unsigned char)*string;
95 @@ -171,35 +188,45 @@ fnmatch1(pattern, string, stringstart, f
96 ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
99 - switch (rangematch(pattern, sc, flags, &newp,
101 + switch (rangematch(pattern, sc, string + sclen, flags,
102 + &newp, &news, &patmbs, &strmbs, loc)) {
105 + return (RETURN_ERROR);
106 +#else /* !__DARWIN_UNIX03 */
108 +#endif /* __DARWIN_UNIX03 */
114 return (FNM_NOMATCH);
119 if (!(flags & FNM_NOESCAPE)) {
120 - pclen = mbrtowc(&pc, pattern, MB_LEN_MAX,
122 + pclen = mbrtowc_l(&pc, pattern, MB_LEN_MAX,
124 if (pclen == (size_t)-1 || pclen == (size_t)-2)
126 + return (RETURN_ERROR);
127 +#else /* !__DARWIN_UNIX03 */
128 return (FNM_NOMATCH);
129 +#endif /* __DARWIN_UNIX03 */
136 +#if !__DARWIN_UNIX03
138 +#endif /* !__DARWIN_UNIX03 */
141 else if ((flags & FNM_CASEFOLD) &&
142 - (towlower(pc) == towlower(sc)))
143 + (towlower_l(pc, loc) == towlower_l(sc, loc)))
146 return (FNM_NOMATCH);
147 @@ -210,18 +237,22 @@ fnmatch1(pattern, string, stringstart, f
152 -rangematch(pattern, test, flags, newp, patmbs)
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;
162 + char **newp, **news;
163 + mbstate_t *patmbs, *strmbs;
167 + int negate, ok, special;
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;
177 * A bracket expression starting with an unquoted circumflex
178 @@ -234,7 +265,7 @@ rangematch(pattern, test, flags, newp, p
181 if (flags & FNM_CASEFOLD)
182 - test = towlower(test);
183 + test = towlower_l(test, loc);
186 * A right bracket shall lose its special meaning and represent
187 @@ -244,8 +275,8 @@ rangematch(pattern, test, flags, newp, p
192 if (*pattern == ']' && pattern > origpat) {
195 } else if (*pattern == '\0') {
196 return (RANGE_ERROR);
197 @@ -253,39 +284,188 @@ rangematch(pattern, test, flags, newp, p
198 return (RANGE_NOMATCH);
199 } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE))
201 - pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs);
202 - if (pclen == (size_t)-1 || pclen == (size_t)-2)
203 - return (RANGE_NOMATCH);
205 + else if (*pattern == '[' && ((special = *(pattern + 1)) == '.' || special == '=' || special == ':')) {
206 + cp = (pattern += 2);
207 + while(cp = strchr(cp, special)) {
208 + if (*(cp + 1) == ']')
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);
222 + /* no multi-character collation symbols as start of range */
223 + if (*(cp + 2) == '-' && *(cp + 3) != EOS
224 + && *(cp + 3) != ']')
225 + return (RANGE_ERROR);
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;
240 + memset(&strmbs, 0, sizeof(strmbs));
243 + memcpy(strmbs, &save, sizeof(save));
244 + string = savestring;
253 + continue; /* no match */
256 + } else if (special == '=') {
258 + memcpy(&save, patmbs, sizeof(save));
259 + ec = __collate_equiv_class(pattern, cp - pattern, patmbs, loc);
261 + return (RANGE_ERROR);
263 + memcpy(patmbs, &save, sizeof(save));
264 + goto treat_like_collating_symbol;
267 + /* no equivalence classes as start of range */
268 + if (*(cp + 2) == '-' && *(cp + 3) != EOS &&
270 + return (RANGE_ERROR);
271 + len = __collate_equiv_match(ec, NULL, 0, test, string, strlen(string), strmbs, &sclen, loc);
273 + return (RANGE_ERROR);
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 &&
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);
292 + if ((charclass = wctype(name)) == 0)
293 + return (RANGE_ERROR);
294 + if (iswctype_l(test, charclass, loc)) {
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);
308 if (flags & FNM_CASEFOLD)
310 + c = towlower_l(c, loc);
312 if (*pattern == '-' && *(pattern + 1) != EOS &&
313 *(pattern + 1) != ']') {
314 if (*++pattern == '\\' && !(flags & FNM_NOESCAPE))
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)
320 - return (RANGE_NOMATCH);
321 + return (RANGE_ERROR);
324 return (RANGE_ERROR);
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);
331 + while(cp = strchr(cp, special)) {
332 + if (*(cp + 1) == ']')
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 */
341 + return (RANGE_ERROR);
346 if (flags & FNM_CASEFOLD)
348 + c2 = towlower_l(c2, loc);
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
356 + __collate_range_cmp(c, test, loc) <= 0
357 + && __collate_range_cmp(test, c2, loc) <= 0
360 - } else if (c == test)
363 + } else if (c == test) {
368 + /* go to end of bracket expression */
370 + while(*pattern != ']') {
372 + return (RANGE_ERROR);
373 + if (*pattern == special) {
374 + if (*++pattern == ']') {
380 + if (!special && *pattern == '[') {
381 + special = *++pattern;
382 + if (special != '.' && special != '=' && special != ':')
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);
394 - *newp = (char *)pattern;
395 + *newp = (char *)++pattern;
396 + *news = (char *)string;
397 return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
399 +#endif /* BUILDING_VARIANT */