1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Guido van Rossum. 7 * 8 * Copyright (c) 2011 The FreeBSD Foundation 9 * All rights reserved. 10 * Portions of this software were developed by David Chisnall 11 * under sponsorship from the FreeBSD Foundation. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * From: @(#)glob.c 8.3 (Berkeley) 10/13/93 38 * From: FreeBSD: head/lib/libc/gen/glob.c 317913 2017-05-07 19:52:56Z jilles 39 */ 40 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include <sys/param.h> 45 #define _WANT_FREEBSD11_STAT 46 #include <sys/stat.h> 47 48 #include <ctype.h> 49 #define _WANT_FREEBSD11_DIRENT 50 #include <dirent.h> 51 #include <errno.h> 52 #include <glob.h> 53 #include <limits.h> 54 #include <pwd.h> 55 #include <stdint.h> 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <string.h> 59 #include <unistd.h> 60 #include <wchar.h> 61 62 #include "collate.h" 63 #include "gen-compat.h" 64 #include "glob-compat11.h" 65 66 /* 67 * glob(3) expansion limits. Stop the expansion if any of these limits 68 * is reached. This caps the runtime in the face of DoS attacks. See 69 * also CVE-2010-2632 70 */ 71 #define GLOB_LIMIT_BRACE 128 /* number of brace calls */ 72 #define GLOB_LIMIT_PATH 65536 /* number of path elements */ 73 #define GLOB_LIMIT_READDIR 16384 /* number of readdirs */ 74 #define GLOB_LIMIT_STAT 1024 /* number of stat system calls */ 75 #define GLOB_LIMIT_STRING ARG_MAX /* maximum total size for paths */ 76 77 struct glob_limit { 78 size_t l_brace_cnt; 79 size_t l_path_lim; 80 size_t l_readdir_cnt; 81 size_t l_stat_cnt; 82 size_t l_string_cnt; 83 }; 84 85 #define DOT L'.' 86 #define EOS L'\0' 87 #define LBRACKET L'[' 88 #define NOT L'!' 89 #define QUESTION L'?' 90 #define QUOTE L'\\' 91 #define RANGE L'-' 92 #define RBRACKET L']' 93 #define SEP L'/' 94 #define STAR L'*' 95 #define TILDE L'~' 96 #define LBRACE L'{' 97 #define RBRACE L'}' 98 #define COMMA L',' 99 100 #define M_QUOTE 0x8000000000ULL 101 #define M_PROTECT 0x4000000000ULL 102 #define M_MASK 0xffffffffffULL 103 #define M_CHAR 0x00ffffffffULL 104 105 typedef uint_fast64_t Char; 106 107 #define CHAR(c) ((Char)((c)&M_CHAR)) 108 #define META(c) ((Char)((c)|M_QUOTE)) 109 #define UNPROT(c) ((c) & ~M_PROTECT) 110 #define M_ALL META(L'*') 111 #define M_END META(L']') 112 #define M_NOT META(L'!') 113 #define M_ONE META(L'?') 114 #define M_RNG META(L'-') 115 #define M_SET META(L'[') 116 #define ismeta(c) (((c)&M_QUOTE) != 0) 117 #ifdef DEBUG 118 #define isprot(c) (((c)&M_PROTECT) != 0) 119 #endif 120 121 static int compare(const void *, const void *); 122 static int g_Ctoc(const Char *, char *, size_t); 123 static int g_lstat(Char *, struct freebsd11_stat *, glob11_t *); 124 static DIR *g_opendir(Char *, glob11_t *); 125 static const Char *g_strchr(const Char *, wchar_t); 126 #ifdef notdef 127 static Char *g_strcat(Char *, const Char *); 128 #endif 129 static int g_stat(Char *, struct freebsd11_stat *, glob11_t *); 130 static int glob0(const Char *, glob11_t *, struct glob_limit *, 131 const char *); 132 static int glob1(Char *, glob11_t *, struct glob_limit *); 133 static int glob2(Char *, Char *, Char *, Char *, glob11_t *, 134 struct glob_limit *); 135 static int glob3(Char *, Char *, Char *, Char *, Char *, glob11_t *, 136 struct glob_limit *); 137 static int globextend(const Char *, glob11_t *, struct glob_limit *, 138 const char *); 139 static const Char * 140 globtilde(const Char *, Char *, size_t, glob11_t *); 141 static int globexp0(const Char *, glob11_t *, struct glob_limit *, 142 const char *); 143 static int globexp1(const Char *, glob11_t *, struct glob_limit *); 144 static int globexp2(const Char *, const Char *, glob11_t *, 145 struct glob_limit *); 146 static int globfinal(glob11_t *, struct glob_limit *, size_t, 147 const char *); 148 static int match(Char *, Char *, Char *); 149 static int err_nomatch(glob11_t *, struct glob_limit *, const char *); 150 static int err_aborted(glob11_t *, int, char *); 151 #ifdef DEBUG 152 static void qprintf(const char *, Char *); 153 #endif 154 155 int 156 freebsd11_glob(const char * __restrict pattern, int flags, 157 int (*errfunc)(const char *, int), glob11_t * __restrict pglob) 158 { 159 struct glob_limit limit = { 0, 0, 0, 0, 0 }; 160 const char *patnext; 161 Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot; 162 mbstate_t mbs; 163 wchar_t wc; 164 size_t clen; 165 int too_long; 166 167 patnext = pattern; 168 if (!(flags & GLOB_APPEND)) { 169 pglob->gl_pathc = 0; 170 pglob->gl_pathv = NULL; 171 if (!(flags & GLOB_DOOFFS)) 172 pglob->gl_offs = 0; 173 } 174 if (flags & GLOB_LIMIT) { 175 limit.l_path_lim = pglob->gl_matchc; 176 if (limit.l_path_lim == 0) 177 limit.l_path_lim = GLOB_LIMIT_PATH; 178 } 179 pglob->gl_flags = flags & ~GLOB_MAGCHAR; 180 pglob->gl_errfunc = errfunc; 181 pglob->gl_matchc = 0; 182 183 bufnext = patbuf; 184 bufend = bufnext + MAXPATHLEN - 1; 185 too_long = 1; 186 if (flags & GLOB_NOESCAPE) { 187 memset(&mbs, 0, sizeof(mbs)); 188 while (bufnext <= bufend) { 189 clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); 190 if (clen == (size_t)-1 || clen == (size_t)-2) 191 return (err_nomatch(pglob, &limit, pattern)); 192 else if (clen == 0) { 193 too_long = 0; 194 break; 195 } 196 *bufnext++ = wc; 197 patnext += clen; 198 } 199 } else { 200 /* Protect the quoted characters. */ 201 memset(&mbs, 0, sizeof(mbs)); 202 while (bufnext <= bufend) { 203 if (*patnext == '\\') { 204 if (*++patnext == '\0') { 205 *bufnext++ = QUOTE; 206 continue; 207 } 208 prot = M_PROTECT; 209 } else 210 prot = 0; 211 clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); 212 if (clen == (size_t)-1 || clen == (size_t)-2) 213 return (err_nomatch(pglob, &limit, pattern)); 214 else if (clen == 0) { 215 too_long = 0; 216 break; 217 } 218 *bufnext++ = wc | prot; 219 patnext += clen; 220 } 221 } 222 if (too_long) 223 return (err_nomatch(pglob, &limit, pattern)); 224 *bufnext = EOS; 225 226 if (flags & GLOB_BRACE) 227 return (globexp0(patbuf, pglob, &limit, pattern)); 228 else 229 return (glob0(patbuf, pglob, &limit, pattern)); 230 } 231 232 static int 233 globexp0(const Char *pattern, glob11_t *pglob, struct glob_limit *limit, 234 const char *origpat) { 235 int rv; 236 size_t oldpathc; 237 238 /* Protect a single {}, for find(1), like csh */ 239 if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) { 240 if ((pglob->gl_flags & GLOB_LIMIT) && 241 limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) { 242 errno = E2BIG; 243 return (GLOB_NOSPACE); 244 } 245 return (glob0(pattern, pglob, limit, origpat)); 246 } 247 248 oldpathc = pglob->gl_pathc; 249 250 if ((rv = globexp1(pattern, pglob, limit)) != 0) 251 return rv; 252 253 return (globfinal(pglob, limit, oldpathc, origpat)); 254 } 255 256 /* 257 * Expand recursively a glob {} pattern. When there is no more expansion 258 * invoke the standard globbing routine to glob the rest of the magic 259 * characters 260 */ 261 static int 262 globexp1(const Char *pattern, glob11_t *pglob, struct glob_limit *limit) 263 { 264 const Char* ptr; 265 266 if ((ptr = g_strchr(pattern, LBRACE)) != NULL) { 267 if ((pglob->gl_flags & GLOB_LIMIT) && 268 limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) { 269 errno = E2BIG; 270 return (GLOB_NOSPACE); 271 } 272 return (globexp2(ptr, pattern, pglob, limit)); 273 } 274 275 return (glob0(pattern, pglob, limit, NULL)); 276 } 277 278 279 /* 280 * Recursive brace globbing helper. Tries to expand a single brace. 281 * If it succeeds then it invokes globexp1 with the new pattern. 282 * If it fails then it tries to glob the rest of the pattern and returns. 283 */ 284 static int 285 globexp2(const Char *ptr, const Char *pattern, glob11_t *pglob, 286 struct glob_limit *limit) 287 { 288 int i, rv; 289 Char *lm, *ls; 290 const Char *pe, *pm, *pm1, *pl; 291 Char patbuf[MAXPATHLEN]; 292 293 /* copy part up to the brace */ 294 for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) 295 continue; 296 *lm = EOS; 297 ls = lm; 298 299 /* Find the balanced brace */ 300 for (i = 0, pe = ++ptr; *pe != EOS; pe++) 301 if (*pe == LBRACKET) { 302 /* Ignore everything between [] */ 303 for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) 304 continue; 305 if (*pe == EOS) { 306 /* 307 * We could not find a matching RBRACKET. 308 * Ignore and just look for RBRACE 309 */ 310 pe = pm; 311 } 312 } 313 else if (*pe == LBRACE) 314 i++; 315 else if (*pe == RBRACE) { 316 if (i == 0) 317 break; 318 i--; 319 } 320 321 /* Non matching braces; just glob the pattern */ 322 if (i != 0 || *pe == EOS) 323 return (glob0(pattern, pglob, limit, NULL)); 324 325 for (i = 0, pl = pm = ptr; pm <= pe; pm++) 326 switch (*pm) { 327 case LBRACKET: 328 /* Ignore everything between [] */ 329 for (pm1 = pm++; *pm != RBRACKET && *pm != EOS; pm++) 330 continue; 331 if (*pm == EOS) { 332 /* 333 * We could not find a matching RBRACKET. 334 * Ignore and just look for RBRACE 335 */ 336 pm = pm1; 337 } 338 break; 339 340 case LBRACE: 341 i++; 342 break; 343 344 case RBRACE: 345 if (i) { 346 i--; 347 break; 348 } 349 /* FALLTHROUGH */ 350 case COMMA: 351 if (i && *pm == COMMA) 352 break; 353 else { 354 /* Append the current string */ 355 for (lm = ls; (pl < pm); *lm++ = *pl++) 356 continue; 357 /* 358 * Append the rest of the pattern after the 359 * closing brace 360 */ 361 for (pl = pe + 1; (*lm++ = *pl++) != EOS;) 362 continue; 363 364 /* Expand the current pattern */ 365 #ifdef DEBUG 366 qprintf("globexp2:", patbuf); 367 #endif 368 rv = globexp1(patbuf, pglob, limit); 369 if (rv) 370 return (rv); 371 372 /* move after the comma, to the next string */ 373 pl = pm + 1; 374 } 375 break; 376 377 default: 378 break; 379 } 380 return (0); 381 } 382 383 384 385 /* 386 * expand tilde from the passwd file. 387 */ 388 static const Char * 389 globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob11_t *pglob) 390 { 391 struct passwd *pwd; 392 char *h, *sc; 393 const Char *p; 394 Char *b, *eb; 395 wchar_t wc; 396 wchar_t wbuf[MAXPATHLEN]; 397 wchar_t *wbufend, *dc; 398 size_t clen; 399 mbstate_t mbs; 400 int too_long; 401 402 if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) 403 return (pattern); 404 405 /* 406 * Copy up to the end of the string or / 407 */ 408 eb = &patbuf[patbuf_len - 1]; 409 for (p = pattern + 1, b = patbuf; 410 b < eb && *p != EOS && UNPROT(*p) != SEP; *b++ = *p++) 411 continue; 412 413 if (*p != EOS && UNPROT(*p) != SEP) 414 return (NULL); 415 416 *b = EOS; 417 h = NULL; 418 419 if (patbuf[0] == EOS) { 420 /* 421 * handle a plain ~ or ~/ by expanding $HOME first (iff 422 * we're not running setuid or setgid) and then trying 423 * the password file 424 */ 425 if ((h = secure_getenv("HOME")) == NULL) { 426 if (((h = getlogin()) != NULL && 427 (pwd = getpwnam(h)) != NULL) || 428 (pwd = getpwuid(getuid())) != NULL) 429 h = pwd->pw_dir; 430 else 431 return (pattern); 432 } 433 } 434 else { 435 /* 436 * Expand a ~user 437 */ 438 if (g_Ctoc(patbuf, (char *)wbuf, sizeof(wbuf))) 439 return (NULL); 440 if ((pwd = getpwnam((char *)wbuf)) == NULL) 441 return (pattern); 442 else 443 h = pwd->pw_dir; 444 } 445 446 /* Copy the home directory */ 447 dc = wbuf; 448 sc = h; 449 wbufend = wbuf + MAXPATHLEN - 1; 450 too_long = 1; 451 memset(&mbs, 0, sizeof(mbs)); 452 while (dc <= wbufend) { 453 clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs); 454 if (clen == (size_t)-1 || clen == (size_t)-2) { 455 /* XXX See initial comment #2. */ 456 wc = (unsigned char)*sc; 457 clen = 1; 458 memset(&mbs, 0, sizeof(mbs)); 459 } 460 if ((*dc++ = wc) == EOS) { 461 too_long = 0; 462 break; 463 } 464 sc += clen; 465 } 466 if (too_long) 467 return (NULL); 468 469 dc = wbuf; 470 for (b = patbuf; b < eb && *dc != EOS; *b++ = *dc++ | M_PROTECT) 471 continue; 472 if (*dc != EOS) 473 return (NULL); 474 475 /* Append the rest of the pattern */ 476 if (*p != EOS) { 477 too_long = 1; 478 while (b <= eb) { 479 if ((*b++ = *p++) == EOS) { 480 too_long = 0; 481 break; 482 } 483 } 484 if (too_long) 485 return (NULL); 486 } else 487 *b = EOS; 488 489 return (patbuf); 490 } 491 492 493 /* 494 * The main glob() routine: compiles the pattern (optionally processing 495 * quotes), calls glob1() to do the real pattern matching, and finally 496 * sorts the list (unless unsorted operation is requested). Returns 0 497 * if things went well, nonzero if errors occurred. 498 */ 499 static int 500 glob0(const Char *pattern, glob11_t *pglob, struct glob_limit *limit, 501 const char *origpat) { 502 const Char *qpatnext; 503 int err; 504 size_t oldpathc; 505 Char *bufnext, c, patbuf[MAXPATHLEN]; 506 507 qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); 508 if (qpatnext == NULL) { 509 errno = E2BIG; 510 return (GLOB_NOSPACE); 511 } 512 oldpathc = pglob->gl_pathc; 513 bufnext = patbuf; 514 515 /* We don't need to check for buffer overflow any more. */ 516 while ((c = *qpatnext++) != EOS) { 517 switch (c) { 518 case LBRACKET: 519 c = *qpatnext; 520 if (c == NOT) 521 ++qpatnext; 522 if (*qpatnext == EOS || 523 g_strchr(qpatnext+1, RBRACKET) == NULL) { 524 *bufnext++ = LBRACKET; 525 if (c == NOT) 526 --qpatnext; 527 break; 528 } 529 *bufnext++ = M_SET; 530 if (c == NOT) 531 *bufnext++ = M_NOT; 532 c = *qpatnext++; 533 do { 534 *bufnext++ = CHAR(c); 535 if (*qpatnext == RANGE && 536 (c = qpatnext[1]) != RBRACKET) { 537 *bufnext++ = M_RNG; 538 *bufnext++ = CHAR(c); 539 qpatnext += 2; 540 } 541 } while ((c = *qpatnext++) != RBRACKET); 542 pglob->gl_flags |= GLOB_MAGCHAR; 543 *bufnext++ = M_END; 544 break; 545 case QUESTION: 546 pglob->gl_flags |= GLOB_MAGCHAR; 547 *bufnext++ = M_ONE; 548 break; 549 case STAR: 550 pglob->gl_flags |= GLOB_MAGCHAR; 551 /* collapse adjacent stars to one, 552 * to avoid exponential behavior 553 */ 554 if (bufnext == patbuf || bufnext[-1] != M_ALL) 555 *bufnext++ = M_ALL; 556 break; 557 default: 558 *bufnext++ = CHAR(c); 559 break; 560 } 561 } 562 *bufnext = EOS; 563 #ifdef DEBUG 564 qprintf("glob0:", patbuf); 565 #endif 566 567 if ((err = glob1(patbuf, pglob, limit)) != 0) 568 return(err); 569 570 if (origpat != NULL) 571 return (globfinal(pglob, limit, oldpathc, origpat)); 572 573 return (0); 574 } 575 576 static int 577 globfinal(glob11_t *pglob, struct glob_limit *limit, size_t oldpathc, 578 const char *origpat) { 579 if (pglob->gl_pathc == oldpathc) 580 return (err_nomatch(pglob, limit, origpat)); 581 582 if (!(pglob->gl_flags & GLOB_NOSORT)) 583 qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, 584 pglob->gl_pathc - oldpathc, sizeof(char *), compare); 585 586 return (0); 587 } 588 589 static int 590 compare(const void *p, const void *q) 591 { 592 return (strcoll(*(char **)p, *(char **)q)); 593 } 594 595 static int 596 glob1(Char *pattern, glob11_t *pglob, struct glob_limit *limit) 597 { 598 Char pathbuf[MAXPATHLEN]; 599 600 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 601 if (*pattern == EOS) 602 return (0); 603 return (glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1, 604 pattern, pglob, limit)); 605 } 606 607 /* 608 * The functions glob2 and glob3 are mutually recursive; there is one level 609 * of recursion for each segment in the pattern that contains one or more 610 * meta characters. 611 */ 612 static int 613 glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern, 614 glob11_t *pglob, struct glob_limit *limit) 615 { 616 struct freebsd11_stat sb; 617 Char *p, *q; 618 int anymeta; 619 620 /* 621 * Loop over pattern segments until end of pattern or until 622 * segment with meta character found. 623 */ 624 for (anymeta = 0;;) { 625 if (*pattern == EOS) { /* End of pattern? */ 626 *pathend = EOS; 627 if (g_lstat(pathbuf, &sb, pglob)) 628 return (0); 629 630 if ((pglob->gl_flags & GLOB_LIMIT) && 631 limit->l_stat_cnt++ >= GLOB_LIMIT_STAT) { 632 errno = E2BIG; 633 return (GLOB_NOSPACE); 634 } 635 if ((pglob->gl_flags & GLOB_MARK) && 636 UNPROT(pathend[-1]) != SEP && 637 (S_ISDIR(sb.st_mode) || 638 (S_ISLNK(sb.st_mode) && 639 g_stat(pathbuf, &sb, pglob) == 0 && 640 S_ISDIR(sb.st_mode)))) { 641 if (pathend + 1 > pathend_last) { 642 errno = E2BIG; 643 return (GLOB_NOSPACE); 644 } 645 *pathend++ = SEP; 646 *pathend = EOS; 647 } 648 ++pglob->gl_matchc; 649 return (globextend(pathbuf, pglob, limit, NULL)); 650 } 651 652 /* Find end of next segment, copy tentatively to pathend. */ 653 q = pathend; 654 p = pattern; 655 while (*p != EOS && UNPROT(*p) != SEP) { 656 if (ismeta(*p)) 657 anymeta = 1; 658 if (q + 1 > pathend_last) { 659 errno = E2BIG; 660 return (GLOB_NOSPACE); 661 } 662 *q++ = *p++; 663 } 664 665 if (!anymeta) { /* No expansion, do next segment. */ 666 pathend = q; 667 pattern = p; 668 while (UNPROT(*pattern) == SEP) { 669 if (pathend + 1 > pathend_last) { 670 errno = E2BIG; 671 return (GLOB_NOSPACE); 672 } 673 *pathend++ = *pattern++; 674 } 675 } else /* Need expansion, recurse. */ 676 return (glob3(pathbuf, pathend, pathend_last, pattern, 677 p, pglob, limit)); 678 } 679 /* NOTREACHED */ 680 } 681 682 static int 683 glob3(Char *pathbuf, Char *pathend, Char *pathend_last, 684 Char *pattern, Char *restpattern, 685 glob11_t *pglob, struct glob_limit *limit) 686 { 687 struct freebsd11_dirent *dp; 688 DIR *dirp; 689 int err, too_long, saverrno, saverrno2; 690 char buf[MAXPATHLEN + MB_LEN_MAX - 1]; 691 692 struct freebsd11_dirent *(*readdirfunc)(DIR *); 693 694 if (pathend > pathend_last) { 695 errno = E2BIG; 696 return (GLOB_NOSPACE); 697 } 698 *pathend = EOS; 699 if (pglob->gl_errfunc != NULL && 700 g_Ctoc(pathbuf, buf, sizeof(buf))) { 701 errno = E2BIG; 702 return (GLOB_NOSPACE); 703 } 704 705 saverrno = errno; 706 errno = 0; 707 if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { 708 if (errno == ENOENT || errno == ENOTDIR) 709 return (0); 710 err = err_aborted(pglob, errno, buf); 711 if (errno == 0) 712 errno = saverrno; 713 return (err); 714 } 715 716 err = 0; 717 718 /* pglob->gl_readdir takes a void *, fix this manually */ 719 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 720 readdirfunc = 721 (struct freebsd11_dirent *(*)(DIR *))pglob->gl_readdir; 722 else 723 readdirfunc = freebsd11_readdir; 724 725 errno = 0; 726 /* Search directory for matching names. */ 727 while ((dp = (*readdirfunc)(dirp)) != NULL) { 728 char *sc; 729 Char *dc; 730 wchar_t wc; 731 size_t clen; 732 mbstate_t mbs; 733 734 if ((pglob->gl_flags & GLOB_LIMIT) && 735 limit->l_readdir_cnt++ >= GLOB_LIMIT_READDIR) { 736 errno = E2BIG; 737 err = GLOB_NOSPACE; 738 break; 739 } 740 741 /* Initial DOT must be matched literally. */ 742 if (dp->d_name[0] == '.' && UNPROT(*pattern) != DOT) { 743 errno = 0; 744 continue; 745 } 746 memset(&mbs, 0, sizeof(mbs)); 747 dc = pathend; 748 sc = dp->d_name; 749 too_long = 1; 750 while (dc <= pathend_last) { 751 clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs); 752 if (clen == (size_t)-1 || clen == (size_t)-2) { 753 /* XXX See initial comment #2. */ 754 wc = (unsigned char)*sc; 755 clen = 1; 756 memset(&mbs, 0, sizeof(mbs)); 757 } 758 if ((*dc++ = wc) == EOS) { 759 too_long = 0; 760 break; 761 } 762 sc += clen; 763 } 764 if (too_long && (err = err_aborted(pglob, ENAMETOOLONG, 765 buf))) { 766 errno = ENAMETOOLONG; 767 break; 768 } 769 if (too_long || !match(pathend, pattern, restpattern)) { 770 *pathend = EOS; 771 errno = 0; 772 continue; 773 } 774 if (errno == 0) 775 errno = saverrno; 776 err = glob2(pathbuf, --dc, pathend_last, restpattern, 777 pglob, limit); 778 if (err) 779 break; 780 errno = 0; 781 } 782 783 saverrno2 = errno; 784 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 785 (*pglob->gl_closedir)(dirp); 786 else 787 closedir(dirp); 788 errno = saverrno2; 789 790 if (err) 791 return (err); 792 793 if (dp == NULL && errno != 0 && 794 (err = err_aborted(pglob, errno, buf))) 795 return (err); 796 797 if (errno == 0) 798 errno = saverrno; 799 return (0); 800 } 801 802 803 /* 804 * Extend the gl_pathv member of a glob11_t structure to accommodate a new item, 805 * add the new item, and update gl_pathc. 806 * 807 * This assumes the BSD realloc, which only copies the block when its size 808 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic 809 * behavior. 810 * 811 * Return 0 if new item added, error code if memory couldn't be allocated. 812 * 813 * Invariant of the glob11_t structure: 814 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 815 * gl_pathv points to (gl_offs + gl_pathc + 1) items. 816 */ 817 static int 818 globextend(const Char *path, glob11_t *pglob, struct glob_limit *limit, 819 const char *origpat) 820 { 821 char **pathv; 822 size_t i, newn, len; 823 char *copy; 824 const Char *p; 825 826 if ((pglob->gl_flags & GLOB_LIMIT) && 827 pglob->gl_matchc > limit->l_path_lim) { 828 errno = E2BIG; 829 return (GLOB_NOSPACE); 830 } 831 832 newn = 2 + pglob->gl_pathc + pglob->gl_offs; 833 /* reallocarray(NULL, newn, size) is equivalent to malloc(newn*size). */ 834 pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv)); 835 if (pathv == NULL) 836 return (GLOB_NOSPACE); 837 838 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 839 /* first time around -- clear initial gl_offs items */ 840 pathv += pglob->gl_offs; 841 for (i = pglob->gl_offs + 1; --i > 0; ) 842 *--pathv = NULL; 843 } 844 pglob->gl_pathv = pathv; 845 846 if (origpat != NULL) 847 copy = strdup(origpat); 848 else { 849 for (p = path; *p++ != EOS;) 850 continue; 851 len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */ 852 if ((copy = malloc(len)) != NULL) { 853 if (g_Ctoc(path, copy, len)) { 854 free(copy); 855 errno = E2BIG; 856 return (GLOB_NOSPACE); 857 } 858 } 859 } 860 if (copy != NULL) { 861 limit->l_string_cnt += strlen(copy) + 1; 862 if ((pglob->gl_flags & GLOB_LIMIT) && 863 limit->l_string_cnt >= GLOB_LIMIT_STRING) { 864 free(copy); 865 errno = E2BIG; 866 return (GLOB_NOSPACE); 867 } 868 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 869 } 870 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 871 return (copy == NULL ? GLOB_NOSPACE : 0); 872 } 873 874 /* 875 * pattern matching function for filenames. 876 */ 877 static int 878 match(Char *name, Char *pat, Char *patend) 879 { 880 int ok, negate_range; 881 Char c, k, *nextp, *nextn; 882 struct xlocale_collate *table = 883 (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE]; 884 885 nextn = NULL; 886 nextp = NULL; 887 888 while (1) { 889 while (pat < patend) { 890 c = *pat++; 891 switch (c & M_MASK) { 892 case M_ALL: 893 if (pat == patend) 894 return (1); 895 if (*name == EOS) 896 return (0); 897 nextn = name + 1; 898 nextp = pat - 1; 899 break; 900 case M_ONE: 901 if (*name++ == EOS) 902 goto fail; 903 break; 904 case M_SET: 905 ok = 0; 906 if ((k = *name++) == EOS) 907 goto fail; 908 negate_range = ((*pat & M_MASK) == M_NOT); 909 if (negate_range != 0) 910 ++pat; 911 while (((c = *pat++) & M_MASK) != M_END) 912 if ((*pat & M_MASK) == M_RNG) { 913 if (table->__collate_load_error ? 914 CHAR(c) <= CHAR(k) && 915 CHAR(k) <= CHAR(pat[1]) : 916 __wcollate_range_cmp(CHAR(c), 917 CHAR(k)) <= 0 && 918 __wcollate_range_cmp(CHAR(k), 919 CHAR(pat[1])) <= 0) 920 ok = 1; 921 pat += 2; 922 } else if (c == k) 923 ok = 1; 924 if (ok == negate_range) 925 goto fail; 926 break; 927 default: 928 if (*name++ != c) 929 goto fail; 930 break; 931 } 932 } 933 if (*name == EOS) 934 return (1); 935 936 fail: 937 if (nextn == NULL) 938 break; 939 pat = nextp; 940 name = nextn; 941 } 942 return (0); 943 } 944 945 /* Free allocated data belonging to a glob11_t structure. */ 946 void 947 freebsd11_globfree(glob11_t *pglob) 948 { 949 size_t i; 950 char **pp; 951 952 if (pglob->gl_pathv != NULL) { 953 pp = pglob->gl_pathv + pglob->gl_offs; 954 for (i = pglob->gl_pathc; i--; ++pp) 955 if (*pp) 956 free(*pp); 957 free(pglob->gl_pathv); 958 pglob->gl_pathv = NULL; 959 } 960 } 961 962 static DIR * 963 g_opendir(Char *str, glob11_t *pglob) 964 { 965 char buf[MAXPATHLEN + MB_LEN_MAX - 1]; 966 967 if (*str == EOS) 968 strcpy(buf, "."); 969 else { 970 if (g_Ctoc(str, buf, sizeof(buf))) { 971 errno = ENAMETOOLONG; 972 return (NULL); 973 } 974 } 975 976 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 977 return ((*pglob->gl_opendir)(buf)); 978 979 return (opendir(buf)); 980 } 981 982 static int 983 g_lstat(Char *fn, struct freebsd11_stat *sb, glob11_t *pglob) 984 { 985 char buf[MAXPATHLEN + MB_LEN_MAX - 1]; 986 987 if (g_Ctoc(fn, buf, sizeof(buf))) { 988 errno = ENAMETOOLONG; 989 return (-1); 990 } 991 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 992 return((*pglob->gl_lstat)(buf, sb)); 993 return (freebsd11_lstat(buf, sb)); 994 } 995 996 static int 997 g_stat(Char *fn, struct freebsd11_stat *sb, glob11_t *pglob) 998 { 999 char buf[MAXPATHLEN + MB_LEN_MAX - 1]; 1000 1001 if (g_Ctoc(fn, buf, sizeof(buf))) { 1002 errno = ENAMETOOLONG; 1003 return (-1); 1004 } 1005 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 1006 return ((*pglob->gl_stat)(buf, sb)); 1007 return (freebsd11_stat(buf, sb)); 1008 } 1009 1010 static const Char * 1011 g_strchr(const Char *str, wchar_t ch) 1012 { 1013 1014 do { 1015 if (*str == ch) 1016 return (str); 1017 } while (*str++); 1018 return (NULL); 1019 } 1020 1021 static int 1022 g_Ctoc(const Char *str, char *buf, size_t len) 1023 { 1024 mbstate_t mbs; 1025 size_t clen; 1026 1027 memset(&mbs, 0, sizeof(mbs)); 1028 while (len >= MB_CUR_MAX) { 1029 clen = wcrtomb(buf, CHAR(*str), &mbs); 1030 if (clen == (size_t)-1) { 1031 /* XXX See initial comment #2. */ 1032 *buf = (char)CHAR(*str); 1033 clen = 1; 1034 memset(&mbs, 0, sizeof(mbs)); 1035 } 1036 if (CHAR(*str) == EOS) 1037 return (0); 1038 str++; 1039 buf += clen; 1040 len -= clen; 1041 } 1042 return (1); 1043 } 1044 1045 static int 1046 err_nomatch(glob11_t *pglob, struct glob_limit *limit, const char *origpat) { 1047 /* 1048 * If there was no match we are going to append the origpat 1049 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified 1050 * and the origpat did not contain any magic characters 1051 * GLOB_NOMAGIC is there just for compatibility with csh. 1052 */ 1053 if ((pglob->gl_flags & GLOB_NOCHECK) || 1054 ((pglob->gl_flags & GLOB_NOMAGIC) && 1055 !(pglob->gl_flags & GLOB_MAGCHAR))) 1056 return (globextend(NULL, pglob, limit, origpat)); 1057 return (GLOB_NOMATCH); 1058 } 1059 1060 static int 1061 err_aborted(glob11_t *pglob, int err, char *buf) { 1062 if ((pglob->gl_errfunc != NULL && pglob->gl_errfunc(buf, err)) || 1063 (pglob->gl_flags & GLOB_ERR)) 1064 return (GLOB_ABORTED); 1065 return (0); 1066 } 1067 1068 #ifdef DEBUG 1069 static void 1070 qprintf(const char *str, Char *s) 1071 { 1072 Char *p; 1073 1074 (void)printf("%s\n", str); 1075 if (s != NULL) { 1076 for (p = s; *p != EOS; p++) 1077 (void)printf("%c", (char)CHAR(*p)); 1078 (void)printf("\n"); 1079 for (p = s; *p != EOS; p++) 1080 (void)printf("%c", (isprot(*p) ? '\\' : ' ')); 1081 (void)printf("\n"); 1082 for (p = s; *p != EOS; p++) 1083 (void)printf("%c", (ismeta(*p) ? '_' : ' ')); 1084 (void)printf("\n"); 1085 } 1086 } 1087 #endif 1088 1089 __sym_compat(glob, freebsd11_glob, FBSD_1.0); 1090 __sym_compat(globfree, freebsd11_globfree, FBSD_1.0); 1091