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