| 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 ( |
| 4 | #include <sys/cdefs.h> |
| 5 | __FBSDID("$FreeBSD: src/lib/libc/gen/glob.c,v 1.28 2010/05/12 17:44:00 gordon Exp $"); |
| 6 | |
| 7 | +#include "xlocale_private.h" |
| 8 | + |
| 9 | /* |
| 10 | * glob(3) -- a superset of the one defined in POSIX 1003.2. |
| 11 | * |
| 12 | @@ -89,6 +91,19 @@ __FBSDID("$FreeBSD: src/lib/libc/gen/glo |
| 13 | |
| 14 | #include "collate.h" |
| 15 | |
| 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 */ |
| 21 | + |
| 22 | +struct glob_limit { |
| 23 | + size_t l_string; |
| 24 | + size_t l_stat; |
| 25 | + size_t l_readdir; |
| 26 | + size_t l_brace; |
| 27 | +}; |
| 28 | + |
| 29 | #define DOLLAR '$' |
| 30 | #define DOT '.' |
| 31 | #define EOS '\0' |
| 32 | @@ -139,62 +154,64 @@ typedef char Char; |
| 33 | #define ismeta(c) (((c)&M_QUOTE) != 0) |
| 34 | |
| 35 | |
| 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); |
| 54 | + |
| 55 | + |
| 56 | +static int g_lstat(Char *, struct stat *, glob_t *, locale_t); |
| 57 | +static DIR *g_opendir(Char *, glob_t *, locale_t); |
| 58 | #ifdef notdef |
| 59 | static Char *g_strcat(Char *, const Char *); |
| 60 | #endif |
| 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 *); |
| 67 | -static const Char * |
| 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); |
| 79 | #ifdef DEBUG |
| 80 | static void qprintf(const char *, Char *); |
| 81 | #endif |
| 82 | |
| 83 | -int |
| 84 | -glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) |
| 85 | +static int |
| 86 | +__glob(const char *pattern, glob_t *pglob) |
| 87 | { |
| 88 | const char *patnext; |
| 89 | - size_t limit; |
| 90 | + struct glob_limit limit = { 0, 0, 0, 0 }; |
| 91 | Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot; |
| 92 | mbstate_t mbs; |
| 93 | wchar_t wc; |
| 94 | size_t clen; |
| 95 | + locale_t loc = __current_locale(); |
| 96 | + int mb_cur_max = MB_CUR_MAX_L(loc); |
| 97 | |
| 98 | patnext = pattern; |
| 99 | - if (!(flags & GLOB_APPEND)) { |
| 100 | + if (!(pglob->gl_flags & GLOB_APPEND)) { |
| 101 | pglob->gl_pathc = 0; |
| 102 | pglob->gl_pathv = NULL; |
| 103 | - if (!(flags & GLOB_DOOFFS)) |
| 104 | + if (!(pglob->gl_flags & GLOB_DOOFFS)) |
| 105 | pglob->gl_offs = 0; |
| 106 | } |
| 107 | - if (flags & GLOB_LIMIT) { |
| 108 | - limit = pglob->gl_matchc; |
| 109 | - if (limit == 0) |
| 110 | - limit = ARG_MAX; |
| 111 | - } else |
| 112 | - limit = 0; |
| 113 | - pglob->gl_flags = flags & ~GLOB_MAGCHAR; |
| 114 | - pglob->gl_errfunc = errfunc; |
| 115 | pglob->gl_matchc = 0; |
| 116 | |
| 117 | bufnext = patbuf; |
| 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); |
| 128 | else if (clen == 0) |
| 129 | @@ -205,7 +222,7 @@ glob(const char *pattern, int flags, int |
| 130 | } else { |
| 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 |
| 139 | prot = M_PROTECT; |
| 140 | } else |
| 141 | prot = 0; |
| 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); |
| 146 | else if (clen == 0) |
| 147 | @@ -225,11 +242,34 @@ glob(const char *pattern, int flags, int |
| 148 | } |
| 149 | *bufnext = EOS; |
| 150 | |
| 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); |
| 155 | else |
| 156 | - return glob0(patbuf, pglob, &limit); |
| 157 | + return glob0(patbuf, pglob, &limit, loc); |
| 158 | +} |
| 159 | + |
| 160 | +int |
| 161 | +glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) |
| 162 | +{ |
| 163 | +#ifdef __BLOCKS__ |
| 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); |
| 170 | +} |
| 171 | + |
| 172 | +#ifdef __BLOCKS__ |
| 173 | +int |
| 174 | +glob_b(const char *pattern, int flags, int (^errblk)(const char *, int), glob_t *pglob) |
| 175 | +{ |
| 176 | + pglob->gl_flags = flags & ~GLOB_MAGCHAR; |
| 177 | + pglob->gl_flags |= _GLOB_ERR_BLOCK; |
| 178 | + pglob->gl_errblk = errblk; |
| 179 | + return __glob(pattern, pglob); |
| 180 | } |
| 181 | +#endif /* __BLOCKS__ */ |
| 182 | |
| 183 | /* |
| 184 | * Expand recursively a glob {} pattern. When there is no more expansion |
| 185 | @@ -237,20 +277,26 @@ glob(const char *pattern, int flags, int |
| 186 | * characters |
| 187 | */ |
| 188 | static 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) |
| 191 | { |
| 192 | const Char* ptr = pattern; |
| 193 | int rv; |
| 194 | |
| 195 | + if ((pglob->gl_flags & GLOB_LIMIT) && |
| 196 | + limit->l_brace++ >= GLOB_LIMIT_BRACE) { |
| 197 | + errno = 0; |
| 198 | + return GLOB_NOSPACE; |
| 199 | + } |
| 200 | + |
| 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); |
| 205 | |
| 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)) |
| 209 | return rv; |
| 210 | |
| 211 | - return glob0(pattern, pglob, limit); |
| 212 | + return glob0(pattern, pglob, limit, loc); |
| 213 | } |
| 214 | |
| 215 | |
| 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. |
| 218 | */ |
| 219 | static int |
| 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) |
| 222 | { |
| 223 | int i; |
| 224 | Char *lm, *ls; |
| 225 | @@ -297,7 +343,7 @@ globexp2(const Char *ptr, const Char *pa |
| 226 | |
| 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); |
| 231 | return 0; |
| 232 | } |
| 233 | |
| 234 | @@ -344,7 +390,7 @@ globexp2(const Char *ptr, const Char *pa |
| 235 | #ifdef DEBUG |
| 236 | qprintf("globexp2:", patbuf); |
| 237 | #endif |
| 238 | - *rv = globexp1(patbuf, pglob, limit); |
| 239 | + *rv = globexp1(patbuf, pglob, limit, loc); |
| 240 | |
| 241 | /* move after the comma, to the next string */ |
| 242 | pl = pm + 1; |
| 243 | @@ -360,10 +406,11 @@ globexp2(const Char *ptr, const Char *pa |
| 244 | |
| 245 | |
| 246 | |
| 247 | +#ifndef BUILDING_VARIANT |
| 248 | /* |
| 249 | * expand tilde from the passwd file. |
| 250 | */ |
| 251 | -static const Char * |
| 252 | +__private_extern__ const Char * |
| 253 | globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) |
| 254 | { |
| 255 | struct passwd *pwd; |
| 256 | @@ -421,6 +468,7 @@ globtilde(const Char *pattern, Char *pat |
| 257 | |
| 258 | return patbuf; |
| 259 | } |
| 260 | +#endif /* BUILDING_VARIANT */ |
| 261 | |
| 262 | |
| 263 | /* |
| 264 | @@ -430,7 +478,7 @@ globtilde(const Char *pattern, Char *pat |
| 265 | * if things went well, nonzero if errors occurred. |
| 266 | */ |
| 267 | static int |
| 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) |
| 270 | { |
| 271 | const Char *qpatnext; |
| 272 | int err; |
| 273 | @@ -443,6 +491,10 @@ glob0(const Char *pattern, glob_t *pglob |
| 274 | |
| 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); |
| 279 | + continue; |
| 280 | + } /* else */ |
| 281 | switch (c) { |
| 282 | case LBRACKET: |
| 283 | c = *qpatnext; |
| 284 | @@ -493,7 +545,7 @@ glob0(const Char *pattern, glob_t *pglob |
| 285 | qprintf("glob0:", patbuf); |
| 286 | #endif |
| 287 | |
| 288 | - if ((err = glob1(patbuf, pglob, limit)) != 0) |
| 289 | + if ((err = glob1(patbuf, pglob, limit, loc)) != 0) |
| 290 | return(err); |
| 291 | |
| 292 | /* |
| 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)); |
| 299 | else |
| 300 | return(GLOB_NOMATCH); |
| 301 | } |
| 302 | @@ -516,14 +568,16 @@ glob0(const Char *pattern, glob_t *pglob |
| 303 | return(0); |
| 304 | } |
| 305 | |
| 306 | -static int |
| 307 | +#ifndef BUILDING_VARIANT |
| 308 | +__private_extern__ int |
| 309 | compare(const void *p, const void *q) |
| 310 | { |
| 311 | - return(strcmp(*(char **)p, *(char **)q)); |
| 312 | + return(strcoll(*(char **)p, *(char **)q)); |
| 313 | } |
| 314 | +#endif /* BUILDING_VARIANT */ |
| 315 | |
| 316 | static int |
| 317 | -glob1(Char *pattern, glob_t *pglob, size_t *limit) |
| 318 | +glob1(Char *pattern, glob_t *pglob, struct glob_limit *limit, locale_t loc) |
| 319 | { |
| 320 | Char pathbuf[MAXPATHLEN]; |
| 321 | |
| 322 | @@ -531,7 +585,7 @@ glob1(Char *pattern, glob_t *pglob, size |
| 323 | if (*pattern == EOS) |
| 324 | return(0); |
| 325 | return(glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1, |
| 326 | - pattern, pglob, limit)); |
| 327 | + pattern, pglob, limit, loc)); |
| 328 | } |
| 329 | |
| 330 | /* |
| 331 | @@ -541,7 +595,7 @@ glob1(Char *pattern, glob_t *pglob, size |
| 332 | */ |
| 333 | static int |
| 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) |
| 337 | { |
| 338 | struct stat sb; |
| 339 | Char *p, *q; |
| 340 | @@ -554,13 +608,20 @@ glob2(Char *pathbuf, Char *pathend, Char |
| 341 | for (anymeta = 0;;) { |
| 342 | if (*pattern == EOS) { /* End of pattern? */ |
| 343 | *pathend = EOS; |
| 344 | - if (g_lstat(pathbuf, &sb, pglob)) |
| 345 | + if (g_lstat(pathbuf, &sb, pglob, loc)) |
| 346 | return(0); |
| 347 | |
| 348 | + if ((pglob->gl_flags & GLOB_LIMIT) && |
| 349 | + limit->l_stat++ >= GLOB_LIMIT_STAT) { |
| 350 | + errno = 0; |
| 351 | + *pathend++ = SEP; |
| 352 | + *pathend = EOS; |
| 353 | + return GLOB_NOSPACE; |
| 354 | + } |
| 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 |
| 364 | *pathend = EOS; |
| 365 | } |
| 366 | ++pglob->gl_matchc; |
| 367 | - return(globextend(pathbuf, pglob, limit)); |
| 368 | + return(globextend(pathbuf, pglob, limit, loc)); |
| 369 | } |
| 370 | |
| 371 | /* Find end of next segment, copy tentatively to pathend. */ |
| 372 | @@ -592,7 +653,7 @@ glob2(Char *pathbuf, Char *pathend, Char |
| 373 | } |
| 374 | } else /* Need expansion, recurse. */ |
| 375 | return(glob3(pathbuf, pathend, pathend_last, pattern, p, |
| 376 | - pglob, limit)); |
| 377 | + pglob, limit, loc)); |
| 378 | } |
| 379 | /* NOTREACHED */ |
| 380 | } |
| 381 | @@ -600,7 +661,7 @@ glob2(Char *pathbuf, Char *pathend, Char |
| 382 | static int |
| 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) |
| 387 | { |
| 388 | struct dirent *dp; |
| 389 | DIR *dirp; |
| 390 | @@ -620,15 +681,22 @@ glob3(Char *pathbuf, Char *pathend, Char |
| 391 | *pathend = EOS; |
| 392 | errno = 0; |
| 393 | |
| 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) |
| 403 | +#ifdef __BLOCKS__ |
| 404 | + if (pglob->gl_flags & _GLOB_ERR_BLOCK) { |
| 405 | + if (pglob->gl_errblk(buf, errno)) |
| 406 | + return (GLOB_ABORTED); |
| 407 | + } else |
| 408 | +#endif /* __BLOCKS__ */ |
| 409 | + if (pglob->gl_errfunc(buf, errno)) |
| 410 | return (GLOB_ABORTED); |
| 411 | } |
| 412 | + if (pglob->gl_flags & GLOB_ERR) |
| 413 | + return (GLOB_ABORTED); |
| 414 | return(0); |
| 415 | } |
| 416 | |
| 417 | @@ -646,6 +714,14 @@ glob3(Char *pathbuf, Char *pathend, Char |
| 418 | size_t clen; |
| 419 | mbstate_t mbs; |
| 420 | |
| 421 | + if ((pglob->gl_flags & GLOB_LIMIT) && |
| 422 | + limit->l_readdir++ >= GLOB_LIMIT_READDIR) { |
| 423 | + errno = 0; |
| 424 | + *pathend++ = SEP; |
| 425 | + *pathend = EOS; |
| 426 | + return GLOB_NOSPACE; |
| 427 | + } |
| 428 | + |
| 429 | /* Initial DOT must be matched literally. */ |
| 430 | if (dp->d_name[0] == DOT && *pattern != DOT) |
| 431 | continue; |
| 432 | @@ -653,7 +729,7 @@ glob3(Char *pathbuf, Char *pathend, Char |
| 433 | dc = pathend; |
| 434 | sc = dp->d_name; |
| 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) { |
| 439 | wc = *sc; |
| 440 | clen = 1; |
| 441 | @@ -663,12 +739,12 @@ glob3(Char *pathbuf, Char *pathend, Char |
| 442 | break; |
| 443 | sc += clen; |
| 444 | } |
| 445 | - if (!match(pathend, pattern, restpattern)) { |
| 446 | + if (!match(pathend, pattern, restpattern, loc)) { |
| 447 | *pathend = EOS; |
| 448 | continue; |
| 449 | } |
| 450 | err = glob2(pathbuf, --dc, pathend_last, restpattern, |
| 451 | - pglob, limit); |
| 452 | + pglob, limit, loc); |
| 453 | if (err) |
| 454 | break; |
| 455 | } |
| 456 | @@ -681,6 +757,7 @@ glob3(Char *pathbuf, Char *pathend, Char |
| 457 | } |
| 458 | |
| 459 | |
| 460 | +#ifndef BUILDING_VARIANT |
| 461 | /* |
| 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. |
| 467 | */ |
| 468 | -static int |
| 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) |
| 472 | { |
| 473 | char **pathv; |
| 474 | size_t i, newsize, len; |
| 475 | char *copy; |
| 476 | const Char *p; |
| 477 | |
| 478 | - if (*limit && pglob->gl_pathc > *limit) { |
| 479 | - errno = 0; |
| 480 | - return (GLOB_NOSPACE); |
| 481 | - } |
| 482 | - |
| 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)) |
| 486 | + goto nospace; |
| 487 | pathv = pglob->gl_pathv ? |
| 488 | realloc((char *)pglob->gl_pathv, newsize) : |
| 489 | malloc(newsize); |
| 490 | @@ -730,24 +805,33 @@ globextend(const Char *path, glob_t *pgl |
| 491 | |
| 492 | for (p = path; *p++;) |
| 493 | continue; |
| 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)) { |
| 500 | free(copy); |
| 501 | return (GLOB_NOSPACE); |
| 502 | } |
| 503 | pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; |
| 504 | } |
| 505 | pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; |
| 506 | + |
| 507 | + if ((pglob->gl_flags & GLOB_LIMIT) && |
| 508 | + (newsize + limit->l_string) >= GLOB_LIMIT_STRING) |
| 509 | + goto nospace; |
| 510 | + |
| 511 | return(copy == NULL ? GLOB_NOSPACE : 0); |
| 512 | +nospace: |
| 513 | + errno = 0; |
| 514 | + return GLOB_NOSPACE; |
| 515 | } |
| 516 | |
| 517 | /* |
| 518 | * pattern matching function for filenames. Each occurrence of the * |
| 519 | * pattern causes a recursion level. |
| 520 | */ |
| 521 | -static int |
| 522 | -match(Char *name, Char *pat, Char *patend) |
| 523 | +__private_extern__ int |
| 524 | +match(Char *name, Char *pat, Char *patend, locale_t loc) |
| 525 | { |
| 526 | int ok, negate_range; |
| 527 | Char c, k; |
| 528 | @@ -759,7 +843,7 @@ match(Char *name, Char *pat, Char *paten |
| 529 | if (pat == patend) |
| 530 | return(1); |
| 531 | do |
| 532 | - if (match(name, pat, patend)) |
| 533 | + if (match(name, pat, patend, loc)) |
| 534 | return(1); |
| 535 | while (*name++ != EOS); |
| 536 | return(0); |
| 537 | @@ -775,10 +859,10 @@ match(Char *name, Char *pat, Char *paten |
| 538 | ++pat; |
| 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 |
| 548 | ) |
| 549 | ok = 1; |
| 550 | pat += 2; |
| 551 | @@ -812,16 +896,17 @@ globfree(glob_t *pglob) |
| 552 | pglob->gl_pathv = NULL; |
| 553 | } |
| 554 | } |
| 555 | +#endif /* !BUILDING_VARIANT */ |
| 556 | |
| 557 | static DIR * |
| 558 | -g_opendir(Char *str, glob_t *pglob) |
| 559 | +g_opendir(Char *str, glob_t *pglob, locale_t loc) |
| 560 | { |
| 561 | char buf[MAXPATHLEN]; |
| 562 | |
| 563 | if (!*str) |
| 564 | strcpy(buf, "."); |
| 565 | else { |
| 566 | - if (g_Ctoc(str, buf, sizeof(buf))) |
| 567 | + if (g_Ctoc(str, buf, sizeof(buf), loc)) |
| 568 | return (NULL); |
| 569 | } |
| 570 | |
| 571 | @@ -832,11 +917,11 @@ g_opendir(Char *str, glob_t *pglob) |
| 572 | } |
| 573 | |
| 574 | static int |
| 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) |
| 577 | { |
| 578 | char buf[MAXPATHLEN]; |
| 579 | |
| 580 | - if (g_Ctoc(fn, buf, sizeof(buf))) { |
| 581 | + if (g_Ctoc(fn, buf, sizeof(buf), loc)) { |
| 582 | errno = ENAMETOOLONG; |
| 583 | return (-1); |
| 584 | } |
| 585 | @@ -846,11 +931,11 @@ g_lstat(Char *fn, struct stat *sb, glob_ |
| 586 | } |
| 587 | |
| 588 | static int |
| 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) |
| 591 | { |
| 592 | char buf[MAXPATHLEN]; |
| 593 | |
| 594 | - if (g_Ctoc(fn, buf, sizeof(buf))) { |
| 595 | + if (g_Ctoc(fn, buf, sizeof(buf), loc)) { |
| 596 | errno = ENAMETOOLONG; |
| 597 | return (-1); |
| 598 | } |
| 599 | @@ -859,7 +944,8 @@ g_stat(Char *fn, struct stat *sb, glob_t |
| 600 | return(stat(buf, sb)); |
| 601 | } |
| 602 | |
| 603 | -static const Char * |
| 604 | +#ifndef BUILDING_VARIANT |
| 605 | +__private_extern__ const Char * |
| 606 | g_strchr(const Char *str, wchar_t ch) |
| 607 | { |
| 608 | |
| 609 | @@ -870,15 +956,16 @@ g_strchr(const Char *str, wchar_t ch) |
| 610 | return (NULL); |
| 611 | } |
| 612 | |
| 613 | -static int |
| 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) |
| 617 | { |
| 618 | mbstate_t mbs; |
| 619 | size_t clen; |
| 620 | + int mb_cur_max = MB_CUR_MAX_L(loc); |
| 621 | |
| 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) |
| 628 | return (1); |
| 629 | if (*str == L'\0') |
| 630 | @@ -908,3 +995,4 @@ qprintf(const char *str, Char *s) |
| 631 | (void)printf("\n"); |
| 632 | } |
| 633 | #endif |
| 634 | +#endif /* !BUILDING_VARIANT */ |