1 /* $OpenBSD: glob.c,v 1.28 2009/02/18 15:50:27 millert Exp $ */ 2 /* 3 * Copyright (c) 1989, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Guido van Rossum. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * glob(3) -- a superset of the one defined in POSIX 1003.2. 36 * 37 * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 38 * 39 * Optional extra services, controlled by flags not defined by POSIX: 40 * 41 * GLOB_QUOTE: 42 * Escaping convention: \ inhibits any special meaning the following 43 * character might have (except \ at end of string is retained). 44 * GLOB_MAGCHAR: 45 * Set in gl_flags if pattern contained a globbing character. 46 * GLOB_NOMAGIC: 47 * Same as GLOB_NOCHECK, but it will only append pattern if it did 48 * not contain any magic characters. [Used in csh style globbing] 49 * GLOB_ALTDIRFUNC: 50 * Use alternately specified directory access functions. 51 * GLOB_TILDE: 52 * expand ~user/foo to the /home/dir/of/user/foo 53 * GLOB_BRACE: 54 * expand {1,2}{a,b} to 1a 1b 2a 2b 55 * gl_matchc: 56 * Number of matches in the current invocation of glob. 57 */ 58 59 #include <sys/param.h> 60 #include <sys/stat.h> 61 62 #include <ctype.h> 63 #include <dirent.h> 64 #include <errno.h> 65 #include <glob.h> 66 #include <pwd.h> 67 #include <stdio.h> 68 #include <stdlib.h> 69 #include <string.h> 70 #include <unistd.h> 71 72 #include "charclass.h" 73 74 #define DOLLAR '$' 75 #define DOT '.' 76 #define EOS '\0' 77 #define LBRACKET '[' 78 #define NOT '!' 79 #define QUESTION '?' 80 #define QUOTE '\\' 81 #define RANGE '-' 82 #define RBRACKET ']' 83 #define SEP '/' 84 #define STAR '*' 85 #define TILDE '~' 86 #define UNDERSCORE '_' 87 #define LBRACE '{' 88 #define RBRACE '}' 89 #define SLASH '/' 90 #define COMMA ',' 91 92 #ifndef DEBUG 93 94 #define M_QUOTE 0x8000 95 #define M_PROTECT 0x4000 96 #define M_MASK 0xffff 97 #define M_ASCII 0x00ff 98 99 typedef u_short Char; 100 101 #else 102 103 #define M_QUOTE 0x80 104 #define M_PROTECT 0x40 105 #define M_MASK 0xff 106 #define M_ASCII 0x7f 107 108 typedef char Char; 109 110 #endif 111 112 113 #define CHAR(c) ((Char)((c)&M_ASCII)) 114 #define META(c) ((Char)((c)|M_QUOTE)) 115 #define M_ALL META('*') 116 #define M_END META(']') 117 #define M_NOT META('!') 118 #define M_ONE META('?') 119 #define M_RNG META('-') 120 #define M_SET META('[') 121 #define M_CLASS META(':') 122 #define ismeta(c) (((c)&M_QUOTE) != 0) 123 124 125 static int compare(const void *, const void *); 126 static int g_Ctoc(const Char *, char *, u_int); 127 static int g_lstat(Char *, struct stat *, glob_t *); 128 static DIR *g_opendir(Char *, glob_t *); 129 static Char *g_strchr(const Char *, int); 130 static int g_strncmp(const Char *, const char *, size_t); 131 static int g_stat(Char *, struct stat *, glob_t *); 132 static int glob0(const Char *, glob_t *); 133 static int glob1(Char *, Char *, glob_t *, size_t *); 134 static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, 135 glob_t *, size_t *); 136 static int glob3(Char *, Char *, Char *, Char *, Char *, 137 Char *, Char *, glob_t *, size_t *); 138 static int globextend(const Char *, glob_t *, size_t *); 139 static const Char * 140 globtilde(const Char *, Char *, size_t, glob_t *); 141 static int globexp1(const Char *, glob_t *); 142 static int globexp2(const Char *, const Char *, glob_t *, int *); 143 static int match(Char *, Char *, Char *); 144 #ifdef DEBUG 145 static void qprintf(const char *, Char *); 146 #endif 147 148 int 149 glob(const char *pattern, int flags, int (*errfunc)(const char *, int), 150 glob_t *pglob) 151 { 152 const u_char *patnext; 153 int c; 154 Char *bufnext, *bufend, patbuf[MAXPATHLEN]; 155 156 patnext = (u_char *) pattern; 157 if (!(flags & GLOB_APPEND)) { 158 pglob->gl_pathc = 0; 159 pglob->gl_pathv = NULL; 160 if (!(flags & GLOB_DOOFFS)) 161 pglob->gl_offs = 0; 162 } 163 pglob->gl_flags = flags & ~GLOB_MAGCHAR; 164 pglob->gl_errfunc = errfunc; 165 pglob->gl_matchc = 0; 166 167 bufnext = patbuf; 168 bufend = bufnext + MAXPATHLEN - 1; 169 if (flags & GLOB_NOESCAPE) 170 while (bufnext < bufend && (c = *patnext++) != EOS) 171 *bufnext++ = c; 172 else { 173 /* Protect the quoted characters. */ 174 while (bufnext < bufend && (c = *patnext++) != EOS) 175 if (c == QUOTE) { 176 if ((c = *patnext++) == EOS) { 177 c = QUOTE; 178 --patnext; 179 } 180 *bufnext++ = c | M_PROTECT; 181 } else 182 *bufnext++ = c; 183 } 184 *bufnext = EOS; 185 186 if (flags & GLOB_BRACE) 187 return globexp1(patbuf, pglob); 188 else 189 return glob0(patbuf, pglob); 190 } 191 192 /* 193 * Expand recursively a glob {} pattern. When there is no more expansion 194 * invoke the standard globbing routine to glob the rest of the magic 195 * characters 196 */ 197 static int 198 globexp1(const Char *pattern, glob_t *pglob) 199 { 200 const Char* ptr = pattern; 201 int rv; 202 203 /* Protect a single {}, for find(1), like csh */ 204 if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) 205 return glob0(pattern, pglob); 206 207 while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) 208 if (!globexp2(ptr, pattern, pglob, &rv)) 209 return rv; 210 211 return glob0(pattern, pglob); 212 } 213 214 215 /* 216 * Recursive brace globbing helper. Tries to expand a single brace. 217 * If it succeeds then it invokes globexp1 with the new pattern. 218 * If it fails then it tries to glob the rest of the pattern and returns. 219 */ 220 static int 221 globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) 222 { 223 int i; 224 Char *lm, *ls; 225 const Char *pe, *pm, *pl; 226 Char patbuf[MAXPATHLEN]; 227 228 /* copy part up to the brace */ 229 for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) 230 ; 231 *lm = EOS; 232 ls = lm; 233 234 /* Find the balanced brace */ 235 for (i = 0, pe = ++ptr; *pe; pe++) 236 if (*pe == LBRACKET) { 237 /* Ignore everything between [] */ 238 for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) 239 ; 240 if (*pe == EOS) { 241 /* 242 * We could not find a matching RBRACKET. 243 * Ignore and just look for RBRACE 244 */ 245 pe = pm; 246 } 247 } else if (*pe == LBRACE) 248 i++; 249 else if (*pe == RBRACE) { 250 if (i == 0) 251 break; 252 i--; 253 } 254 255 /* Non matching braces; just glob the pattern */ 256 if (i != 0 || *pe == EOS) { 257 *rv = glob0(patbuf, pglob); 258 return 0; 259 } 260 261 for (i = 0, pl = pm = ptr; pm <= pe; pm++) { 262 switch (*pm) { 263 case LBRACKET: 264 /* Ignore everything between [] */ 265 for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) 266 ; 267 if (*pm == EOS) { 268 /* 269 * We could not find a matching RBRACKET. 270 * Ignore and just look for RBRACE 271 */ 272 pm = pl; 273 } 274 break; 275 276 case LBRACE: 277 i++; 278 break; 279 280 case RBRACE: 281 if (i) { 282 i--; 283 break; 284 } 285 /* FALLTHROUGH */ 286 case COMMA: 287 if (i && *pm == COMMA) 288 break; 289 else { 290 /* Append the current string */ 291 for (lm = ls; (pl < pm); *lm++ = *pl++) 292 ; 293 294 /* 295 * Append the rest of the pattern after the 296 * closing brace 297 */ 298 for (pl = pe + 1; (*lm++ = *pl++) != EOS; ) 299 ; 300 301 /* Expand the current pattern */ 302 #ifdef DEBUG 303 qprintf("globexp2:", patbuf); 304 #endif 305 *rv = globexp1(patbuf, pglob); 306 307 /* move after the comma, to the next string */ 308 pl = pm + 1; 309 } 310 break; 311 312 default: 313 break; 314 } 315 } 316 *rv = 0; 317 return 0; 318 } 319 320 321 322 /* 323 * expand tilde from the passwd file. 324 */ 325 static const Char * 326 globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) 327 { 328 struct passwd *pwd; 329 char *h; 330 const Char *p; 331 Char *b, *eb; 332 333 if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) 334 return pattern; 335 336 /* Copy up to the end of the string or / */ 337 eb = &patbuf[patbuf_len - 1]; 338 for (p = pattern + 1, h = (char *) patbuf; 339 h < (char *)eb && *p && *p != SLASH; *h++ = *p++) 340 ; 341 342 *h = EOS; 343 344 #if 0 345 if (h == (char *)eb) 346 return what; 347 #endif 348 349 if (((char *) patbuf)[0] == EOS) { 350 /* 351 * handle a plain ~ or ~/ by expanding $HOME 352 * first and then trying the password file 353 */ 354 if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { 355 if ((pwd = getpwuid(getuid())) == NULL) 356 return pattern; 357 else 358 h = pwd->pw_dir; 359 } 360 } else { 361 /* 362 * Expand a ~user 363 */ 364 if ((pwd = getpwnam((char*) patbuf)) == NULL) 365 return pattern; 366 else 367 h = pwd->pw_dir; 368 } 369 370 /* Copy the home directory */ 371 for (b = patbuf; b < eb && *h; *b++ = *h++) 372 ; 373 374 /* Append the rest of the pattern */ 375 while (b < eb && (*b++ = *p++) != EOS) 376 ; 377 *b = EOS; 378 379 return patbuf; 380 } 381 382 static int 383 g_strncmp(const Char *s1, const char *s2, size_t n) 384 { 385 int rv = 0; 386 387 while (n--) { 388 rv = *(Char *)s1 - *(const unsigned char *)s2++; 389 if (rv) 390 break; 391 if (*s1++ == '\0') 392 break; 393 } 394 return rv; 395 } 396 397 static int 398 g_charclass(const Char **patternp, Char **bufnextp) 399 { 400 const Char *pattern = *patternp + 1; 401 Char *bufnext = *bufnextp; 402 const Char *colon; 403 struct cclass *cc; 404 size_t len; 405 406 if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']') 407 return 1; /* not a character class */ 408 409 len = (size_t)(colon - pattern); 410 for (cc = cclasses; cc->name != NULL; cc++) { 411 if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0') 412 break; 413 } 414 if (cc->name == NULL) 415 return -1; /* invalid character class */ 416 *bufnext++ = M_CLASS; 417 *bufnext++ = (Char)(cc - &cclasses[0]); 418 *bufnextp = bufnext; 419 *patternp += len + 3; 420 421 return 0; 422 } 423 424 /* 425 * The main glob() routine: compiles the pattern (optionally processing 426 * quotes), calls glob1() to do the real pattern matching, and finally 427 * sorts the list (unless unsorted operation is requested). Returns 0 428 * if things went well, nonzero if errors occurred. It is not an error 429 * to find no matches. 430 */ 431 static int 432 glob0(const Char *pattern, glob_t *pglob) 433 { 434 const Char *qpatnext; 435 int c, err, oldpathc; 436 Char *bufnext, patbuf[MAXPATHLEN]; 437 size_t limit = 0; 438 439 qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); 440 oldpathc = pglob->gl_pathc; 441 bufnext = patbuf; 442 443 /* We don't need to check for buffer overflow any more. */ 444 while ((c = *qpatnext++) != EOS) { 445 switch (c) { 446 case LBRACKET: 447 c = *qpatnext; 448 if (c == NOT) 449 ++qpatnext; 450 if (*qpatnext == EOS || 451 g_strchr(qpatnext+1, RBRACKET) == NULL) { 452 *bufnext++ = LBRACKET; 453 if (c == NOT) 454 --qpatnext; 455 break; 456 } 457 *bufnext++ = M_SET; 458 if (c == NOT) 459 *bufnext++ = M_NOT; 460 c = *qpatnext++; 461 do { 462 if (c == LBRACKET && *qpatnext == ':') { 463 do { 464 err = g_charclass(&qpatnext, 465 &bufnext); 466 if (err) 467 break; 468 c = *qpatnext++; 469 } while (c == LBRACKET && *qpatnext == ':'); 470 if (err == -1 && 471 !(pglob->gl_flags & GLOB_NOCHECK)) 472 return GLOB_NOMATCH; 473 if (c == RBRACKET) 474 break; 475 } 476 *bufnext++ = CHAR(c); 477 if (*qpatnext == RANGE && 478 (c = qpatnext[1]) != RBRACKET) { 479 *bufnext++ = M_RNG; 480 *bufnext++ = CHAR(c); 481 qpatnext += 2; 482 } 483 } while ((c = *qpatnext++) != RBRACKET); 484 pglob->gl_flags |= GLOB_MAGCHAR; 485 *bufnext++ = M_END; 486 break; 487 case QUESTION: 488 pglob->gl_flags |= GLOB_MAGCHAR; 489 *bufnext++ = M_ONE; 490 break; 491 case STAR: 492 pglob->gl_flags |= GLOB_MAGCHAR; 493 /* collapse adjacent stars to one, 494 * to avoid exponential behavior 495 */ 496 if (bufnext == patbuf || bufnext[-1] != M_ALL) 497 *bufnext++ = M_ALL; 498 break; 499 default: 500 *bufnext++ = CHAR(c); 501 break; 502 } 503 } 504 *bufnext = EOS; 505 #ifdef DEBUG 506 qprintf("glob0:", patbuf); 507 #endif 508 509 if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) 510 return(err); 511 512 /* 513 * If there was no match we are going to append the pattern 514 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified 515 * and the pattern did not contain any magic characters 516 * GLOB_NOMAGIC is there just for compatibility with csh. 517 */ 518 if (pglob->gl_pathc == oldpathc) { 519 if ((pglob->gl_flags & GLOB_NOCHECK) || 520 ((pglob->gl_flags & GLOB_NOMAGIC) && 521 !(pglob->gl_flags & GLOB_MAGCHAR))) 522 return(globextend(pattern, pglob, &limit)); 523 else 524 return(GLOB_NOMATCH); 525 } 526 if (!(pglob->gl_flags & GLOB_NOSORT)) 527 qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, 528 pglob->gl_pathc - oldpathc, sizeof(char *), compare); 529 return(0); 530 } 531 532 static int 533 compare(const void *p, const void *q) 534 { 535 return(strcmp(*(char **)p, *(char **)q)); 536 } 537 538 static int 539 glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) 540 { 541 Char pathbuf[MAXPATHLEN]; 542 543 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 544 if (*pattern == EOS) 545 return(0); 546 return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, 547 pathbuf, pathbuf+MAXPATHLEN-1, 548 pattern, pattern_last, pglob, limitp)); 549 } 550 551 /* 552 * The functions glob2 and glob3 are mutually recursive; there is one level 553 * of recursion for each segment in the pattern that contains one or more 554 * meta characters. 555 */ 556 static int 557 glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, 558 Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) 559 { 560 struct stat sb; 561 Char *p, *q; 562 int anymeta; 563 564 /* 565 * Loop over pattern segments until end of pattern or until 566 * segment with meta character found. 567 */ 568 for (anymeta = 0;;) { 569 if (*pattern == EOS) { /* End of pattern? */ 570 *pathend = EOS; 571 if (g_lstat(pathbuf, &sb, pglob)) 572 return(0); 573 574 if (((pglob->gl_flags & GLOB_MARK) && 575 pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || 576 (S_ISLNK(sb.st_mode) && 577 (g_stat(pathbuf, &sb, pglob) == 0) && 578 S_ISDIR(sb.st_mode)))) { 579 if (pathend+1 > pathend_last) 580 return (1); 581 *pathend++ = SEP; 582 *pathend = EOS; 583 } 584 ++pglob->gl_matchc; 585 return(globextend(pathbuf, pglob, limitp)); 586 } 587 588 /* Find end of next segment, copy tentatively to pathend. */ 589 q = pathend; 590 p = pattern; 591 while (*p != EOS && *p != SEP) { 592 if (ismeta(*p)) 593 anymeta = 1; 594 if (q+1 > pathend_last) 595 return (1); 596 *q++ = *p++; 597 } 598 599 if (!anymeta) { /* No expansion, do next segment. */ 600 pathend = q; 601 pattern = p; 602 while (*pattern == SEP) { 603 if (pathend+1 > pathend_last) 604 return (1); 605 *pathend++ = *pattern++; 606 } 607 } else 608 /* Need expansion, recurse. */ 609 return(glob3(pathbuf, pathbuf_last, pathend, 610 pathend_last, pattern, p, pattern_last, 611 pglob, limitp)); 612 } 613 /* NOTREACHED */ 614 } 615 616 static int 617 glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, 618 Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, 619 size_t *limitp) 620 { 621 struct dirent *dp; 622 DIR *dirp; 623 int err; 624 char buf[MAXPATHLEN]; 625 626 /* 627 * The readdirfunc declaration can't be prototyped, because it is 628 * assigned, below, to two functions which are prototyped in glob.h 629 * and dirent.h as taking pointers to differently typed opaque 630 * structures. 631 */ 632 struct dirent *(*readdirfunc)(void *); 633 634 if (pathend > pathend_last) 635 return (1); 636 *pathend = EOS; 637 errno = 0; 638 639 if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { 640 /* TODO: don't call for ENOENT or ENOTDIR? */ 641 if (pglob->gl_errfunc) { 642 if (g_Ctoc(pathbuf, buf, sizeof(buf))) 643 return(GLOB_ABORTED); 644 if (pglob->gl_errfunc(buf, errno) || 645 pglob->gl_flags & GLOB_ERR) 646 return(GLOB_ABORTED); 647 } 648 return(0); 649 } 650 651 err = 0; 652 653 /* Search directory for matching names. */ 654 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 655 readdirfunc = pglob->gl_readdir; 656 else 657 readdirfunc = (struct dirent *(*)(void *))readdir; 658 while ((dp = (*readdirfunc)(dirp))) { 659 u_char *sc; 660 Char *dc; 661 662 /* Initial DOT must be matched literally. */ 663 if (dp->d_name[0] == DOT && *pattern != DOT) 664 continue; 665 dc = pathend; 666 sc = (u_char *) dp->d_name; 667 while (dc < pathend_last && (*dc++ = *sc++) != EOS) 668 ; 669 if (dc >= pathend_last) { 670 *dc = EOS; 671 err = 1; 672 break; 673 } 674 675 if (!match(pathend, pattern, restpattern)) { 676 *pathend = EOS; 677 continue; 678 } 679 err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, 680 restpattern, restpattern_last, pglob, limitp); 681 if (err) 682 break; 683 } 684 685 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 686 (*pglob->gl_closedir)(dirp); 687 else 688 closedir(dirp); 689 return(err); 690 } 691 692 693 /* 694 * Extend the gl_pathv member of a glob_t structure to accommodate a new item, 695 * add the new item, and update gl_pathc. 696 * 697 * This assumes the BSD realloc, which only copies the block when its size 698 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic 699 * behavior. 700 * 701 * Return 0 if new item added, error code if memory couldn't be allocated. 702 * 703 * Invariant of the glob_t structure: 704 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 705 * gl_pathv points to (gl_offs + gl_pathc + 1) items. 706 */ 707 static int 708 globextend(const Char *path, glob_t *pglob, size_t *limitp) 709 { 710 char **pathv; 711 int i; 712 u_int newsize, len; 713 char *copy; 714 const Char *p; 715 716 newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); 717 pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : 718 malloc(newsize); 719 if (pathv == NULL) { 720 if (pglob->gl_pathv) { 721 free(pglob->gl_pathv); 722 pglob->gl_pathv = NULL; 723 } 724 return(GLOB_NOSPACE); 725 } 726 727 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 728 /* first time around -- clear initial gl_offs items */ 729 pathv += pglob->gl_offs; 730 for (i = pglob->gl_offs; --i >= 0; ) 731 *--pathv = NULL; 732 } 733 pglob->gl_pathv = pathv; 734 735 for (p = path; *p++;) 736 ; 737 len = (size_t)(p - path); 738 *limitp += len; 739 if ((copy = malloc(len)) != NULL) { 740 if (g_Ctoc(path, copy, len)) { 741 free(copy); 742 return(GLOB_NOSPACE); 743 } 744 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 745 } 746 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 747 748 if ((pglob->gl_flags & GLOB_LIMIT) && 749 newsize + *limitp >= ARG_MAX) { 750 errno = 0; 751 return(GLOB_NOSPACE); 752 } 753 754 return(copy == NULL ? GLOB_NOSPACE : 0); 755 } 756 757 758 /* 759 * pattern matching function for filenames. Each occurrence of the * 760 * pattern causes a recursion level. 761 */ 762 static int 763 match(Char *name, Char *pat, Char *patend) 764 { 765 int ok, negate_range; 766 Char c, k; 767 768 while (pat < patend) { 769 c = *pat++; 770 switch (c & M_MASK) { 771 case M_ALL: 772 if (pat == patend) 773 return(1); 774 do { 775 if (match(name, pat, patend)) 776 return(1); 777 } while (*name++ != EOS); 778 return(0); 779 case M_ONE: 780 if (*name++ == EOS) 781 return(0); 782 break; 783 case M_SET: 784 ok = 0; 785 if ((k = *name++) == EOS) 786 return(0); 787 if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) 788 ++pat; 789 while (((c = *pat++) & M_MASK) != M_END) { 790 if ((c & M_MASK) == M_CLASS) { 791 int idx = *pat & M_MASK; 792 if (idx < NCCLASSES && 793 cclasses[idx].isctype(k)) 794 ok = 1; 795 ++pat; 796 } 797 if ((*pat & M_MASK) == M_RNG) { 798 if (c <= k && k <= pat[1]) 799 ok = 1; 800 pat += 2; 801 } else if (c == k) 802 ok = 1; 803 } 804 if (ok == negate_range) 805 return(0); 806 break; 807 default: 808 if (*name++ != c) 809 return(0); 810 break; 811 } 812 } 813 return(*name == EOS); 814 } 815 816 /* Free allocated data belonging to a glob_t structure. */ 817 void 818 globfree(glob_t *pglob) 819 { 820 int i; 821 char **pp; 822 823 if (pglob->gl_pathv != NULL) { 824 pp = pglob->gl_pathv + pglob->gl_offs; 825 for (i = pglob->gl_pathc; i--; ++pp) 826 if (*pp) 827 free(*pp); 828 free(pglob->gl_pathv); 829 pglob->gl_pathv = NULL; 830 } 831 } 832 833 static DIR * 834 g_opendir(Char *str, glob_t *pglob) 835 { 836 char buf[MAXPATHLEN]; 837 838 if (!*str) 839 strlcpy(buf, ".", sizeof buf); 840 else { 841 if (g_Ctoc(str, buf, sizeof(buf))) 842 return(NULL); 843 } 844 845 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 846 return((*pglob->gl_opendir)(buf)); 847 848 return(opendir(buf)); 849 } 850 851 static int 852 g_lstat(Char *fn, struct stat *sb, glob_t *pglob) 853 { 854 char buf[MAXPATHLEN]; 855 856 if (g_Ctoc(fn, buf, sizeof(buf))) 857 return(-1); 858 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 859 return((*pglob->gl_lstat)(buf, sb)); 860 return(lstat(buf, sb)); 861 } 862 863 static int 864 g_stat(Char *fn, struct stat *sb, glob_t *pglob) 865 { 866 char buf[MAXPATHLEN]; 867 868 if (g_Ctoc(fn, buf, sizeof(buf))) 869 return(-1); 870 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 871 return((*pglob->gl_stat)(buf, sb)); 872 return(stat(buf, sb)); 873 } 874 875 static Char * 876 g_strchr(const Char *str, int ch) 877 { 878 do { 879 if (*str == ch) 880 return ((Char *)str); 881 } while (*str++); 882 return (NULL); 883 } 884 885 static int 886 g_Ctoc(const Char *str, char *buf, u_int len) 887 { 888 889 while (len--) { 890 if ((*buf++ = *str++) == EOS) 891 return (0); 892 } 893 return (1); 894 } 895 896 #ifdef DEBUG 897 static void 898 qprintf(const char *str, Char *s) 899 { 900 Char *p; 901 902 (void)printf("%s:\n", str); 903 for (p = s; *p; p++) 904 (void)printf("%c", CHAR(*p)); 905 (void)printf("\n"); 906 for (p = s; *p; p++) 907 (void)printf("%c", *p & M_PROTECT ? '"' : ' '); 908 (void)printf("\n"); 909 for (p = s; *p; p++) 910 (void)printf("%c", ismeta(*p) ? '_' : ' '); 911 (void)printf("\n"); 912 } 913 #endif 914