1 --- glob.c.orig 2011-01-25 17:41:37.000000000 -0800
2 +++ glob.c 2011-01-26 11:50:09.000000000 -0800
3 @@ -36,6 +36,8 @@ static char sccsid[] = "@(#)glob.c 8.3 (
5 __FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.28 2010/05/12 17:44:00 gordon Exp $");
7 +#include "xlocale_private.h"
10 * glob(3) -- a superset of the one defined in POSIX 1003.2.
12 @@ -89,6 +91,19 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/glo
16 +#define GLOB_LIMIT_STRING 65536 /* number of readdirs */
17 +#define GLOB_LIMIT_STAT 128 /* number of stat system calls */
18 +#define GLOB_LIMIT_READDIR 16384 /* total buffer size of path strings */
19 +#define GLOB_LIMIT_PATH 1024 /* number of path elements */
20 +#define GLOB_LIMIT_BRACE 128 /* Number of brace calls */
32 @@ -139,62 +154,64 @@ typedef char Char;
33 #define ismeta(c) (((c)&M_QUOTE) != 0)
36 -static int compare(const void *, const void *);
37 -static int g_Ctoc(const Char *, char *, size_t);
38 -static int g_lstat(Char *, struct stat *, glob_t *);
39 -static DIR *g_opendir(Char *, glob_t *);
40 -static const Char *g_strchr(const Char *, wchar_t);
41 +#define compare __gl_compare
42 +#define g_Ctoc __gl_g_Ctoc
43 +#define g_strchr __gl_g_strchr
44 +#define globextend __gl_globextend
45 +#define globtilde __gl_globtilde
46 +#define match __gl_match
47 +__private_extern__ int compare(const void *, const void *);
48 +__private_extern__ int g_Ctoc(const Char *, char *, size_t, locale_t);
49 +__private_extern__ const Char *g_strchr(const Char *, wchar_t);
50 +__private_extern__ int globextend(const Char *, glob_t *, struct glob_limit *, locale_t);
51 +__private_extern__ const Char *
52 + globtilde(const Char *, Char *, size_t, glob_t *);
53 +__private_extern__ int match(Char *, Char *, Char *, locale_t);
56 +static int g_lstat(Char *, struct stat *, glob_t *, locale_t);
57 +static DIR *g_opendir(Char *, glob_t *, locale_t);
59 static Char *g_strcat(Char *, const Char *);
61 -static int g_stat(Char *, struct stat *, glob_t *);
62 -static int glob0(const Char *, glob_t *, size_t *);
63 -static int glob1(Char *, glob_t *, size_t *);
64 -static int glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *);
65 -static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, size_t *);
66 -static int globextend(const Char *, glob_t *, size_t *);
68 - globtilde(const Char *, Char *, size_t, glob_t *);
69 -static int globexp1(const Char *, glob_t *, size_t *);
70 -static int globexp2(const Char *, const Char *, glob_t *, int *, size_t *);
71 -static int match(Char *, Char *, Char *);
72 +static int g_stat(Char *, struct stat *, glob_t *, locale_t);
73 +static int glob0(const Char *, glob_t *, struct glob_limit *, locale_t);
74 +static int glob1(Char *, glob_t *, struct glob_limit *, locale_t);
75 +static int glob2(Char *, Char *, Char *, Char *, glob_t *, struct glob_limit *, locale_t);
76 +static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, struct glob_limit *, locale_t);
77 +static int globexp1(const Char *, glob_t *, struct glob_limit *, locale_t);
78 +static int globexp2(const Char *, const Char *, glob_t *, int *, struct glob_limit *, locale_t);
80 static void qprintf(const char *, Char *);
84 -glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob)
86 +__glob(const char *pattern, glob_t *pglob)
90 + struct glob_limit limit = { 0, 0, 0, 0 };
91 Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
95 + locale_t loc = __current_locale();
96 + int mb_cur_max = MB_CUR_MAX_L(loc);
99 - if (!(flags & GLOB_APPEND)) {
100 + if (!(pglob->gl_flags & GLOB_APPEND)) {
102 pglob->gl_pathv = NULL;
103 - if (!(flags & GLOB_DOOFFS))
104 + if (!(pglob->gl_flags & GLOB_DOOFFS))
107 - if (flags & GLOB_LIMIT) {
108 - limit = pglob->gl_matchc;
113 - pglob->gl_flags = flags & ~GLOB_MAGCHAR;
114 - pglob->gl_errfunc = errfunc;
115 pglob->gl_matchc = 0;
118 bufend = bufnext + MAXPATHLEN - 1;
119 - if (flags & GLOB_NOESCAPE) {
120 + if (pglob->gl_flags & GLOB_NOESCAPE) {
121 memset(&mbs, 0, sizeof(mbs));
122 - while (bufend - bufnext >= MB_CUR_MAX) {
123 - clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
124 + while (bufend - bufnext >= mb_cur_max) {
125 + clen = mbrtowc_l(&wc, patnext, MB_LEN_MAX, &mbs, loc);
126 if (clen == (size_t)-1 || clen == (size_t)-2)
127 return (GLOB_NOMATCH);
129 @@ -205,7 +222,7 @@ glob(const char *pattern, int flags, int
131 /* Protect the quoted characters. */
132 memset(&mbs, 0, sizeof(mbs));
133 - while (bufend - bufnext >= MB_CUR_MAX) {
134 + while (bufend - bufnext >= mb_cur_max) {
135 if (*patnext == QUOTE) {
136 if (*++patnext == EOS) {
137 *bufnext++ = QUOTE | M_PROTECT;
138 @@ -214,7 +231,7 @@ glob(const char *pattern, int flags, int
142 - clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
143 + clen = mbrtowc_l(&wc, patnext, MB_LEN_MAX, &mbs, loc);
144 if (clen == (size_t)-1 || clen == (size_t)-2)
145 return (GLOB_NOMATCH);
147 @@ -225,11 +242,34 @@ glob(const char *pattern, int flags, int
151 - if (flags & GLOB_BRACE)
152 - return globexp1(patbuf, pglob, &limit);
153 + if (pglob->gl_flags & GLOB_BRACE)
154 + return globexp1(patbuf, pglob, &limit, loc);
156 - return glob0(patbuf, pglob, &limit);
157 + return glob0(patbuf, pglob, &limit, loc);
161 +glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob)
164 + pglob->gl_flags = flags & ~(GLOB_MAGCHAR | _GLOB_ERR_BLOCK);
165 +#else /* !__BLOCKS__ */
166 + pglob->gl_flags = flags & ~GLOB_MAGCHAR;
167 +#endif /* __BLOCKS__ */
168 + pglob->gl_errfunc = errfunc;
169 + return __glob(pattern, pglob);
174 +glob_b(const char *pattern, int flags, int (^errblk)(const char *, int), glob_t *pglob)
176 + pglob->gl_flags = flags & ~GLOB_MAGCHAR;
177 + pglob->gl_flags |= _GLOB_ERR_BLOCK;
178 + pglob->gl_errblk = errblk;
179 + return __glob(pattern, pglob);
181 +#endif /* __BLOCKS__ */
184 * Expand recursively a glob {} pattern. When there is no more expansion
185 @@ -237,20 +277,26 @@ glob(const char *pattern, int flags, int
189 -globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
190 +globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit, locale_t loc)
192 const Char* ptr = pattern;
195 + if ((pglob->gl_flags & GLOB_LIMIT) &&
196 + limit->l_brace++ >= GLOB_LIMIT_BRACE) {
198 + return GLOB_NOSPACE;
201 /* Protect a single {}, for find(1), like csh */
202 if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
203 - return glob0(pattern, pglob, limit);
204 + return glob0(pattern, pglob, limit, loc);
206 while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
207 - if (!globexp2(ptr, pattern, pglob, &rv, limit))
208 + if (!globexp2(ptr, pattern, pglob, &rv, limit, loc))
211 - return glob0(pattern, pglob, limit);
212 + return glob0(pattern, pglob, limit, loc);
216 @@ -260,7 +306,7 @@ globexp1(const Char *pattern, glob_t *pg
217 * If it fails then it tries to glob the rest of the pattern and returns.
220 -globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *limit)
221 +globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, struct glob_limit *limit, locale_t loc)
225 @@ -297,7 +343,7 @@ globexp2(const Char *ptr, const Char *pa
227 /* Non matching braces; just glob the pattern */
228 if (i != 0 || *pe == EOS) {
229 - *rv = glob0(patbuf, pglob, limit);
230 + *rv = glob0(patbuf, pglob, limit, loc);
234 @@ -344,7 +390,7 @@ globexp2(const Char *ptr, const Char *pa
236 qprintf("globexp2:", patbuf);
238 - *rv = globexp1(patbuf, pglob, limit);
239 + *rv = globexp1(patbuf, pglob, limit, loc);
241 /* move after the comma, to the next string */
243 @@ -360,10 +406,11 @@ globexp2(const Char *ptr, const Char *pa
247 +#ifndef BUILDING_VARIANT
249 * expand tilde from the passwd file.
252 +__private_extern__ const Char *
253 globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
256 @@ -421,6 +468,7 @@ globtilde(const Char *pattern, Char *pat
260 +#endif /* BUILDING_VARIANT */
264 @@ -430,7 +478,7 @@ globtilde(const Char *pattern, Char *pat
265 * if things went well, nonzero if errors occurred.
268 -glob0(const Char *pattern, glob_t *pglob, size_t *limit)
269 +glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, locale_t loc)
271 const Char *qpatnext;
273 @@ -443,6 +491,10 @@ glob0(const Char *pattern, glob_t *pglob
275 /* We don't need to check for buffer overflow any more. */
276 while ((c = *qpatnext++) != EOS) {
277 + if (c & M_PROTECT) {
278 + *bufnext++ = CHAR(c);
284 @@ -493,7 +545,7 @@ glob0(const Char *pattern, glob_t *pglob
285 qprintf("glob0:", patbuf);
288 - if ((err = glob1(patbuf, pglob, limit)) != 0)
289 + if ((err = glob1(patbuf, pglob, limit, loc)) != 0)
293 @@ -506,7 +558,7 @@ glob0(const Char *pattern, glob_t *pglob
294 if (((pglob->gl_flags & GLOB_NOCHECK) ||
295 ((pglob->gl_flags & GLOB_NOMAGIC) &&
296 !(pglob->gl_flags & GLOB_MAGCHAR))))
297 - return(globextend(pattern, pglob, limit));
298 + return(globextend(pattern, pglob, limit, loc));
300 return(GLOB_NOMATCH);
302 @@ -516,14 +568,16 @@ glob0(const Char *pattern, glob_t *pglob
307 +#ifndef BUILDING_VARIANT
308 +__private_extern__ int
309 compare(const void *p, const void *q)
311 - return(strcmp(*(char **)p, *(char **)q));
312 + return(strcoll(*(char **)p, *(char **)q));
314 +#endif /* BUILDING_VARIANT */
317 -glob1(Char *pattern, glob_t *pglob, size_t *limit)
318 +glob1(Char *pattern, glob_t *pglob, struct glob_limit *limit, locale_t loc)
320 Char pathbuf[MAXPATHLEN];
322 @@ -531,7 +585,7 @@ glob1(Char *pattern, glob_t *pglob, size
325 return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
326 - pattern, pglob, limit));
327 + pattern, pglob, limit, loc));
331 @@ -541,7 +595,7 @@ glob1(Char *pattern, glob_t *pglob, size
334 glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
335 - glob_t *pglob, size_t *limit)
336 + glob_t *pglob, struct glob_limit *limit, locale_t loc)
340 @@ -554,13 +608,20 @@ glob2(Char *pathbuf, Char *pathend, Char
341 for (anymeta = 0;;) {
342 if (*pattern == EOS) { /* End of pattern? */
344 - if (g_lstat(pathbuf, &sb, pglob))
345 + if (g_lstat(pathbuf, &sb, pglob, loc))
348 + if ((pglob->gl_flags & GLOB_LIMIT) &&
349 + limit->l_stat++ >= GLOB_LIMIT_STAT) {
353 + return GLOB_NOSPACE;
355 if (((pglob->gl_flags & GLOB_MARK) &&
356 pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
357 || (S_ISLNK(sb.st_mode) &&
358 - (g_stat(pathbuf, &sb, pglob) == 0) &&
359 + (g_stat(pathbuf, &sb, pglob, loc) == 0) &&
360 S_ISDIR(sb.st_mode)))) {
361 if (pathend + 1 > pathend_last)
362 return (GLOB_ABORTED);
363 @@ -568,7 +629,7 @@ glob2(Char *pathbuf, Char *pathend, Char
367 - return(globextend(pathbuf, pglob, limit));
368 + return(globextend(pathbuf, pglob, limit, loc));
371 /* Find end of next segment, copy tentatively to pathend. */
372 @@ -592,7 +653,7 @@ glob2(Char *pathbuf, Char *pathend, Char
374 } else /* Need expansion, recurse. */
375 return(glob3(pathbuf, pathend, pathend_last, pattern, p,
377 + pglob, limit, loc));
381 @@ -600,7 +661,7 @@ glob2(Char *pathbuf, Char *pathend, Char
383 glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
384 Char *pattern, Char *restpattern,
385 - glob_t *pglob, size_t *limit)
386 + glob_t *pglob, struct glob_limit *limit, locale_t loc)
390 @@ -620,15 +681,22 @@ glob3(Char *pathbuf, Char *pathend, Char
394 - if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
395 + if ((dirp = g_opendir(pathbuf, pglob, loc)) == NULL) {
396 /* TODO: don't call for ENOENT or ENOTDIR? */
397 if (pglob->gl_errfunc) {
398 - if (g_Ctoc(pathbuf, buf, sizeof(buf)))
399 + if (g_Ctoc(pathbuf, buf, sizeof(buf), loc))
400 return (GLOB_ABORTED);
401 - if (pglob->gl_errfunc(buf, errno) ||
402 - pglob->gl_flags & GLOB_ERR)
404 + if (pglob->gl_flags & _GLOB_ERR_BLOCK) {
405 + if (pglob->gl_errblk(buf, errno))
406 + return (GLOB_ABORTED);
408 +#endif /* __BLOCKS__ */
409 + if (pglob->gl_errfunc(buf, errno))
410 return (GLOB_ABORTED);
412 + if (pglob->gl_flags & GLOB_ERR)
413 + return (GLOB_ABORTED);
417 @@ -646,6 +714,14 @@ glob3(Char *pathbuf, Char *pathend, Char
421 + if ((pglob->gl_flags & GLOB_LIMIT) &&
422 + limit->l_readdir++ >= GLOB_LIMIT_READDIR) {
426 + return GLOB_NOSPACE;
429 /* Initial DOT must be matched literally. */
430 if (dp->d_name[0] == DOT && *pattern != DOT)
432 @@ -653,7 +729,7 @@ glob3(Char *pathbuf, Char *pathend, Char
435 while (dc < pathend_last) {
436 - clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
437 + clen = mbrtowc_l(&wc, sc, MB_LEN_MAX, &mbs, loc);
438 if (clen == (size_t)-1 || clen == (size_t)-2) {
441 @@ -663,12 +739,12 @@ glob3(Char *pathbuf, Char *pathend, Char
445 - if (!match(pathend, pattern, restpattern)) {
446 + if (!match(pathend, pattern, restpattern, loc)) {
450 err = glob2(pathbuf, --dc, pathend_last, restpattern,
452 + pglob, limit, loc);
456 @@ -681,6 +757,7 @@ glob3(Char *pathbuf, Char *pathend, Char
460 +#ifndef BUILDING_VARIANT
462 * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
463 * add the new item, and update gl_pathc.
464 @@ -695,20 +772,18 @@ glob3(Char *pathbuf, Char *pathend, Char
465 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
466 * gl_pathv points to (gl_offs + gl_pathc + 1) items.
469 -globextend(const Char *path, glob_t *pglob, size_t *limit)
470 +__private_extern__ int
471 +globextend(const Char *path, glob_t *pglob, struct glob_limit *limit, locale_t loc)
474 size_t i, newsize, len;
478 - if (*limit && pglob->gl_pathc > *limit) {
480 - return (GLOB_NOSPACE);
483 newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
484 + if ((pglob->gl_flags & GLOB_LIMIT) &&
485 + newsize > GLOB_LIMIT_PATH * sizeof(*pathv))
487 pathv = pglob->gl_pathv ?
488 realloc((char *)pglob->gl_pathv, newsize) :
490 @@ -730,24 +805,33 @@ globextend(const Char *path, glob_t *pgl
492 for (p = path; *p++;)
494 - len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */
495 + len = MB_CUR_MAX_L(loc) * (size_t)(p - path); /* XXX overallocation */
496 + limit->l_string += len;
497 if ((copy = malloc(len)) != NULL) {
498 - if (g_Ctoc(path, copy, len)) {
499 + if (g_Ctoc(path, copy, len, loc)) {
501 return (GLOB_NOSPACE);
503 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
505 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
507 + if ((pglob->gl_flags & GLOB_LIMIT) &&
508 + (newsize + limit->l_string) >= GLOB_LIMIT_STRING)
511 return(copy == NULL ? GLOB_NOSPACE : 0);
514 + return GLOB_NOSPACE;
518 * pattern matching function for filenames. Each occurrence of the *
519 * pattern causes a recursion level.
522 -match(Char *name, Char *pat, Char *patend)
523 +__private_extern__ int
524 +match(Char *name, Char *pat, Char *patend, locale_t loc)
526 int ok, negate_range;
528 @@ -759,7 +843,7 @@ match(Char *name, Char *pat, Char *paten
532 - if (match(name, pat, patend))
533 + if (match(name, pat, patend, loc))
535 while (*name++ != EOS);
537 @@ -775,10 +859,10 @@ match(Char *name, Char *pat, Char *paten
539 while (((c = *pat++) & M_MASK) != M_END)
540 if ((*pat & M_MASK) == M_RNG) {
541 - if (__collate_load_error ?
542 + if (loc->__collate_load_error ?
543 CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
544 - __collate_range_cmp(CHAR(c), CHAR(k)) <= 0
545 - && __collate_range_cmp(CHAR(k), CHAR(pat[1])) <= 0
546 + __collate_range_cmp(CHAR(c), CHAR(k), loc) <= 0
547 + && __collate_range_cmp(CHAR(k), CHAR(pat[1]), loc) <= 0
551 @@ -812,16 +896,17 @@ globfree(glob_t *pglob)
552 pglob->gl_pathv = NULL;
555 +#endif /* !BUILDING_VARIANT */
558 -g_opendir(Char *str, glob_t *pglob)
559 +g_opendir(Char *str, glob_t *pglob, locale_t loc)
561 char buf[MAXPATHLEN];
566 - if (g_Ctoc(str, buf, sizeof(buf)))
567 + if (g_Ctoc(str, buf, sizeof(buf), loc))
571 @@ -832,11 +917,11 @@ g_opendir(Char *str, glob_t *pglob)
575 -g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
576 +g_lstat(Char *fn, struct stat *sb, glob_t *pglob, locale_t loc)
578 char buf[MAXPATHLEN];
580 - if (g_Ctoc(fn, buf, sizeof(buf))) {
581 + if (g_Ctoc(fn, buf, sizeof(buf), loc)) {
582 errno = ENAMETOOLONG;
585 @@ -846,11 +931,11 @@ g_lstat(Char *fn, struct stat *sb, glob_
589 -g_stat(Char *fn, struct stat *sb, glob_t *pglob)
590 +g_stat(Char *fn, struct stat *sb, glob_t *pglob, locale_t loc)
592 char buf[MAXPATHLEN];
594 - if (g_Ctoc(fn, buf, sizeof(buf))) {
595 + if (g_Ctoc(fn, buf, sizeof(buf), loc)) {
596 errno = ENAMETOOLONG;
599 @@ -859,7 +944,8 @@ g_stat(Char *fn, struct stat *sb, glob_t
600 return(stat(buf, sb));
604 +#ifndef BUILDING_VARIANT
605 +__private_extern__ const Char *
606 g_strchr(const Char *str, wchar_t ch)
609 @@ -870,15 +956,16 @@ g_strchr(const Char *str, wchar_t ch)
614 -g_Ctoc(const Char *str, char *buf, size_t len)
615 +__private_extern__ int
616 +g_Ctoc(const Char *str, char *buf, size_t len, locale_t loc)
620 + int mb_cur_max = MB_CUR_MAX_L(loc);
622 memset(&mbs, 0, sizeof(mbs));
623 - while (len >= MB_CUR_MAX) {
624 - clen = wcrtomb(buf, *str, &mbs);
625 + while (len >= mb_cur_max) {
626 + clen = wcrtomb_l(buf, *str, &mbs, loc);
627 if (clen == (size_t)-1)
630 @@ -908,3 +995,4 @@ qprintf(const char *str, Char *s)
634 +#endif /* !BUILDING_VARIANT */