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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 2013 Gary Mills 35 */ 36 37 /* 38 * glob(3) -- a superset of the one defined in POSIX 1003.2. 39 * 40 * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 41 * 42 * Optional extra services, controlled by flags not defined by POSIX: 43 * 44 * GLOB_QUOTE: 45 * Escaping convention: \ inhibits any special meaning the following 46 * character might have (except \ at end of string is retained). 47 * GLOB_MAGCHAR: 48 * Set in gl_flags if pattern contained a globbing character. 49 * GLOB_NOMAGIC: 50 * Same as GLOB_NOCHECK, but it will only append pattern if it did 51 * not contain any magic characters. [Used in csh style globbing] 52 * GLOB_ALTDIRFUNC: 53 * Use alternately specified directory access functions. 54 * GLOB_TILDE: 55 * expand ~user/foo to the /home/dir/of/user/foo 56 * GLOB_BRACE: 57 * expand {1,2}{a,b} to 1a 1b 2a 2b 58 * gl_matchc: 59 * Number of matches in the current invocation of glob. 60 */ 61 62 #include "lint.h" 63 64 #include <sys/param.h> 65 #include <sys/stat.h> 66 67 #include <ctype.h> 68 #include <dirent.h> 69 #include <errno.h> 70 #include <glob.h> 71 #include <limits.h> 72 #include <pwd.h> 73 #include <stdint.h> 74 #include <stdio.h> 75 #include <stdlib.h> 76 #include <string.h> 77 #include <unistd.h> 78 #include <wchar.h> 79 #include <wctype.h> 80 81 /* 82 * This is the legacy glob_t prior to illumos enhancement 1097, 83 * used when old programs call the old libc glob functions. 84 * (New programs call the _glob_ext, _globfree_ext functions.) 85 * This struct should be considered "carved in stone". 86 */ 87 typedef struct old_glob { 88 size_t gl_pathc; /* Count of paths matched by pattern */ 89 char **gl_pathv; /* List of matched pathnames */ 90 size_t gl_offs; /* # of slots reserved in gl_pathv */ 91 /* following are internal to the implementation */ 92 char **gl_pathp; /* gl_pathv + gl_offs */ 93 int gl_pathn; /* # of elements allocated */ 94 } old_glob_t; 95 96 /* 97 * For old programs, the external names need to be the old names: 98 * glob() and globfree() . We've redefined those already to 99 * _glob_ext() and _globfree_ext() . Now redefine old_glob() 100 * and old_globfree() to glob() and globfree() . 101 */ 102 #ifdef __PRAGMA_REDEFINE_EXTNAME 103 #pragma redefine_extname old_glob glob 104 #pragma redefine_extname old_globfree globfree 105 #endif /* __PRAGMA_REDEFINE_EXTNAME */ 106 extern int old_glob(const char *, int, int (*)(const char *, int), 107 old_glob_t *); 108 extern void old_globfree(old_glob_t *); 109 110 /* 111 * The various extensions to glob(3C) allow for stat and dirent structures to 112 * show up whose size may change in a largefile environment. If libc defines 113 * _FILE_OFFSET_BITS to be 64 that is the key to indicate that we're building 114 * the LFS version of this file. As such, we rename the public functions here, 115 * _glob_ext() and _globfree_ext() to have a 64 suffix. When building the LFS 116 * version, we do not include the old versions. 117 */ 118 #if !defined(_LP64) && _FILE_OFFSET_BITS == 64 119 #define _glob_ext _glob_ext64 120 #define _globfree_ext _globfree_ext64 121 #endif /* !_LP64 && _FILE_OFFSET_BITS == 64 */ 122 123 #define DOLLAR '$' 124 #define DOT '.' 125 #define EOS '\0' 126 #define LBRACKET '[' 127 #define NOT '!' 128 #define QUESTION '?' 129 #define QUOTE '\\' 130 #define RANGE '-' 131 #define RBRACKET ']' 132 #define SEP '/' 133 #define STAR '*' 134 #define TILDE '~' 135 #define UNDERSCORE '_' 136 #define LBRACE '{' 137 #define RBRACE '}' 138 #define SLASH '/' 139 #define COMMA ',' 140 #define COLON ':' 141 142 #define M_QUOTE 0x800000 143 #define M_PROTECT 0x400000 144 145 typedef struct wcat { 146 wchar_t w_wc; 147 uint_t w_at; 148 } wcat_t; 149 150 #define M_ALL '*' /* Plus M_QUOTE */ 151 #define M_END ']' /* Plus M_QUOTE */ 152 #define M_NOT '!' /* Plus M_QUOTE */ 153 #define M_ONE '?' /* Plus M_QUOTE */ 154 #define M_RNG '-' /* Plus M_QUOTE */ 155 #define M_SET '[' /* Plus M_QUOTE */ 156 #define M_CLASS ':' /* Plus M_QUOTE */ 157 #define ismeta(c) (((c).w_at&M_QUOTE) != 0) 158 159 #define INITIAL 8 /* initial pathv allocation */ 160 161 #define GLOB_LIMIT_MALLOC 65536 162 #define GLOB_LIMIT_STAT 2048 163 #define GLOB_LIMIT_READDIR 16384 164 165 struct glob_lim { 166 size_t glim_malloc; 167 size_t glim_stat; 168 size_t glim_readdir; 169 }; 170 171 struct glob_path_stat { 172 char *gps_path; 173 struct stat *gps_stat; 174 }; 175 176 static int compare(const void *, const void *); 177 static int compare_gps(const void *, const void *); 178 static int g_Ctoc(const wcat_t *, char *, uint_t); 179 static int g_lstat(wcat_t *, struct stat *, glob_t *); 180 static DIR *g_opendir(wcat_t *, glob_t *); 181 static wcat_t *g_strchr(const wcat_t *, wchar_t); 182 static int g_stat(wcat_t *, struct stat *, glob_t *); 183 static int glob0(const wcat_t *, glob_t *, struct glob_lim *, 184 int (*)(const char *, int)); 185 static int glob1(wcat_t *, wcat_t *, glob_t *, struct glob_lim *, 186 int (*)(const char *, int)); 187 static int glob2(wcat_t *, wcat_t *, wcat_t *, wcat_t *, wcat_t *, 188 wcat_t *, glob_t *, struct glob_lim *, 189 int (*)(const char *, int)); 190 static int glob3(wcat_t *, wcat_t *, wcat_t *, wcat_t *, wcat_t *, 191 wcat_t *, wcat_t *, glob_t *, struct glob_lim *, 192 int (*)(const char *, int)); 193 static int globextend(const wcat_t *, glob_t *, struct glob_lim *, 194 struct stat *); 195 static 196 const wcat_t *globtilde(const wcat_t *, wcat_t *, size_t, glob_t *); 197 static int globexp1(const wcat_t *, glob_t *, struct glob_lim *, 198 int (*)(const char *, int)); 199 static int globexp2(const wcat_t *, const wcat_t *, glob_t *, 200 struct glob_lim *, int (*)(const char *, int)); 201 static int match(wcat_t *, wcat_t *, wcat_t *); 202 203 /* 204 * Extended glob() function, selected by #pragma redefine_extname 205 * in glob.h with the external name _glob_ext() . 206 */ 207 int 208 _glob_ext(const char *pattern, int flags, int (*errfunc)(const char *, int), 209 glob_t *pglob) 210 { 211 const char *patnext; 212 int n; 213 size_t patlen; 214 wchar_t c; 215 wcat_t *bufnext, *bufend, patbuf[PATH_MAX]; 216 struct glob_lim limit = { 0, 0, 0 }; 217 218 patnext = pattern; 219 if (!(flags & GLOB_APPEND)) { 220 pglob->gl_pathc = 0; 221 pglob->gl_pathn = 0; 222 pglob->gl_pathv = NULL; 223 if ((flags & GLOB_KEEPSTAT) != 0) 224 pglob->gl_statv = NULL; 225 if (!(flags & GLOB_DOOFFS)) 226 pglob->gl_offs = 0; 227 } 228 pglob->gl_flags = flags & ~GLOB_MAGCHAR; 229 pglob->gl_matchc = 0; 230 231 if ((patlen = strnlen(pattern, PATH_MAX)) == PATH_MAX) 232 return (GLOB_NOMATCH); 233 234 if (pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX || 235 pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1) 236 return (GLOB_NOSPACE); 237 238 bufnext = patbuf; 239 bufend = bufnext + PATH_MAX - 1; 240 patlen += 1; 241 if (flags & GLOB_NOESCAPE) { 242 while (bufnext < bufend) { 243 if ((n = mbtowc(&c, patnext, patlen)) > 0) { 244 patnext += n; 245 patlen -= n; 246 bufnext->w_at = 0; 247 (bufnext++)->w_wc = c; 248 } else if (n == 0) { 249 break; 250 } else { 251 return (GLOB_NOMATCH); 252 } 253 } 254 } else { 255 /* Protect the quoted characters. */ 256 while (bufnext < bufend) { 257 if ((n = mbtowc(&c, patnext, patlen)) > 0) { 258 patnext += n; 259 patlen -= n; 260 if (c == QUOTE) { 261 n = mbtowc(&c, patnext, patlen); 262 if (n < 0) 263 return (GLOB_NOMATCH); 264 if (n > 0) { 265 patnext += n; 266 patlen -= n; 267 } 268 if (n == 0) 269 c = QUOTE; 270 bufnext->w_at = M_PROTECT; 271 (bufnext++)->w_wc = c; 272 } else { 273 bufnext->w_at = 0; 274 (bufnext++)->w_wc = c; 275 } 276 } else if (n == 0) { 277 break; 278 } else { 279 return (GLOB_NOMATCH); 280 } 281 } 282 } 283 bufnext->w_at = 0; 284 bufnext->w_wc = EOS; 285 286 if (flags & GLOB_BRACE) 287 return (globexp1(patbuf, pglob, &limit, errfunc)); 288 else 289 return (glob0(patbuf, pglob, &limit, errfunc)); 290 } 291 292 /* 293 * Expand recursively a glob {} pattern. When there is no more expansion 294 * invoke the standard globbing routine to glob the rest of the magic 295 * characters 296 */ 297 static int 298 globexp1(const wcat_t *pattern, glob_t *pglob, struct glob_lim *limitp, 299 int (*errfunc)(const char *, int)) 300 { 301 const wcat_t *ptr = pattern; 302 303 /* Protect a single {}, for find(1), like csh */ 304 if (pattern[0].w_wc == LBRACE && pattern[1].w_wc == RBRACE && 305 pattern[2].w_wc == EOS) 306 return (glob0(pattern, pglob, limitp, errfunc)); 307 308 if ((ptr = (const wcat_t *) g_strchr(ptr, LBRACE)) != NULL) 309 return (globexp2(ptr, pattern, pglob, limitp, errfunc)); 310 311 return (glob0(pattern, pglob, limitp, errfunc)); 312 } 313 314 315 /* 316 * Recursive brace globbing helper. Tries to expand a single brace. 317 * If it succeeds then it invokes globexp1 with the new pattern. 318 * If it fails then it tries to glob the rest of the pattern and returns. 319 */ 320 static int 321 globexp2(const wcat_t *ptr, const wcat_t *pattern, glob_t *pglob, 322 struct glob_lim *limitp, int (*errfunc)(const char *, int)) 323 { 324 int i, rv; 325 wcat_t *lm, *ls; 326 const wcat_t *pe, *pm, *pl; 327 wcat_t patbuf[PATH_MAX]; 328 329 /* copy part up to the brace */ 330 for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) 331 ; 332 lm->w_at = 0; 333 lm->w_wc = EOS; 334 ls = lm; 335 336 /* Find the balanced brace */ 337 for (i = 0, pe = ++ptr; pe->w_wc != EOS; pe++) 338 if (pe->w_wc == LBRACKET) { 339 /* Ignore everything between [] */ 340 for (pm = pe++; pe->w_wc != RBRACKET && 341 pe->w_wc != EOS; pe++) 342 ; 343 if (pe->w_wc == EOS) { 344 /* 345 * We could not find a matching RBRACKET. 346 * Ignore and just look for RBRACE 347 */ 348 pe = pm; 349 } 350 } else if (pe->w_wc == LBRACE) { 351 i++; 352 } else if (pe->w_wc == RBRACE) { 353 if (i == 0) 354 break; 355 i--; 356 } 357 358 /* Non matching braces; just glob the pattern */ 359 if (i != 0 || pe->w_wc == EOS) 360 return (glob0(patbuf, pglob, limitp, errfunc)); 361 362 for (i = 0, pl = pm = ptr; pm <= pe; pm++) { 363 switch (pm->w_wc) { 364 case LBRACKET: 365 /* Ignore everything between [] */ 366 for (pl = pm++; pm->w_wc != RBRACKET && pm->w_wc != EOS; 367 pm++) 368 ; 369 if (pm->w_wc == EOS) { 370 /* 371 * We could not find a matching RBRACKET. 372 * Ignore and just look for RBRACE 373 */ 374 pm = pl; 375 } 376 break; 377 378 case LBRACE: 379 i++; 380 break; 381 382 case RBRACE: 383 if (i) { 384 i--; 385 break; 386 } 387 /* FALLTHROUGH */ 388 case COMMA: 389 if (i && pm->w_wc == COMMA) 390 break; 391 else { 392 /* Append the current string */ 393 for (lm = ls; (pl < pm); *lm++ = *pl++) 394 ; 395 396 /* 397 * Append the rest of the pattern after the 398 * closing brace 399 */ 400 for (pl = pe + 1; 401 (*lm++ = *pl++).w_wc != EOS; /* */) 402 ; 403 404 /* Expand the current pattern */ 405 rv = globexp1(patbuf, pglob, limitp, errfunc); 406 if (rv && rv != GLOB_NOMATCH) 407 return (rv); 408 409 /* move after the comma, to the next string */ 410 pl = pm + 1; 411 } 412 break; 413 414 default: 415 break; 416 } 417 } 418 return (0); 419 } 420 421 422 423 /* 424 * expand tilde from the passwd file. 425 */ 426 static const wcat_t * 427 globtilde(const wcat_t *pattern, wcat_t *patbuf, size_t patbuf_len, 428 glob_t *pglob) 429 { 430 struct passwd *pwd; 431 char *h; 432 const wcat_t *p; 433 wcat_t *b, *eb, *q; 434 int n; 435 size_t lenh; 436 wchar_t c; 437 438 if (pattern->w_wc != TILDE || !(pglob->gl_flags & GLOB_TILDE)) 439 return (pattern); 440 441 /* Copy up to the end of the string or / */ 442 eb = &patbuf[patbuf_len - 1]; 443 for (p = pattern + 1, q = patbuf; 444 q < eb && p->w_wc != EOS && p->w_wc != SLASH; *q++ = *p++) 445 ; 446 447 q->w_at = 0; 448 q->w_wc = EOS; 449 450 /* What to do if patbuf is full? */ 451 452 if (patbuf[0].w_wc == EOS) { 453 /* 454 * handle a plain ~ or ~/ by expanding $HOME 455 * first and then trying the password file 456 */ 457 if (issetugid() != 0) 458 return (pattern); 459 if ((h = getenv("HOME")) == NULL) { 460 if ((pwd = getpwuid(getuid())) == NULL) 461 return (pattern); 462 else 463 h = pwd->pw_dir; 464 } 465 } else { 466 /* 467 * Expand a ~user 468 */ 469 if ((pwd = getpwnam((char *)patbuf)) == NULL) 470 return (pattern); 471 else 472 h = pwd->pw_dir; 473 } 474 475 /* Copy the home directory */ 476 lenh = strlen(h) + 1; 477 for (b = patbuf; b < eb && *h != EOS; b++) { 478 if ((n = mbtowc(&c, h, lenh)) > 0) { 479 h += n; 480 lenh -= n; 481 b->w_at = 0; 482 b->w_wc = c; 483 } else if (n < 0) { 484 return (pattern); 485 } else { 486 break; 487 } 488 } 489 490 /* Append the rest of the pattern */ 491 while (b < eb && (*b++ = *p++).w_wc != EOS) 492 ; 493 b->w_at = 0; 494 b->w_wc = EOS; 495 496 return (patbuf); 497 } 498 499 static int 500 g_charclass(const wcat_t **patternp, wcat_t **bufnextp) 501 { 502 const wcat_t *pattern = *patternp + 1; 503 wcat_t *bufnext = *bufnextp; 504 const wcat_t *colon; 505 char cbuf[MB_LEN_MAX + 32]; 506 wctype_t cc; 507 size_t len; 508 509 if ((colon = g_strchr(pattern, COLON)) == NULL || 510 colon[1].w_wc != RBRACKET) 511 return (1); /* not a character class */ 512 513 len = (size_t)(colon - pattern); 514 if (len + MB_LEN_MAX + 1 > sizeof (cbuf)) 515 return (-1); /* invalid character class */ 516 { 517 wchar_t w; 518 const wcat_t *s1 = pattern; 519 char *s2 = cbuf; 520 size_t n = len; 521 522 /* Copy the string. */ 523 while (n > 0) { 524 w = (s1++)->w_wc; 525 /* Character class names must be ASCII. */ 526 if (iswascii(w)) { 527 n--; 528 *s2++ = w; 529 } else { 530 return (-1); /* invalid character class */ 531 } 532 } 533 *s2 = EOS; 534 } 535 if ((cc = wctype(cbuf)) == 0) 536 return (-1); /* invalid character class */ 537 bufnext->w_at = M_QUOTE; 538 (bufnext++)->w_wc = M_CLASS; 539 bufnext->w_at = 0; 540 (bufnext++)->w_wc = cc; 541 *bufnextp = bufnext; 542 *patternp += len + 3; 543 544 return (0); 545 } 546 547 /* 548 * The main glob() routine: compiles the pattern (optionally processing 549 * quotes), calls glob1() to do the real pattern matching, and finally 550 * sorts the list (unless unsorted operation is requested). Returns 0 551 * if things went well, nonzero if errors occurred. It is not an error 552 * to find no matches. 553 */ 554 static int 555 glob0(const wcat_t *pattern, glob_t *pglob, struct glob_lim *limitp, 556 int (*errfunc)(const char *, int)) 557 { 558 const wcat_t *qpatnext; 559 int err, oldpathc; 560 wchar_t c; 561 int a; 562 wcat_t *bufnext, patbuf[PATH_MAX]; 563 564 qpatnext = globtilde(pattern, patbuf, PATH_MAX, pglob); 565 oldpathc = pglob->gl_pathc; 566 bufnext = patbuf; 567 568 /* 569 * We don't need to check for buffer overflow any more. 570 * The pattern has already been copied to an internal buffer. 571 */ 572 while ((a = qpatnext->w_at), (c = (qpatnext++)->w_wc) != EOS) { 573 switch (c) { 574 case LBRACKET: 575 if (a != 0) { 576 bufnext->w_at = a; 577 (bufnext++)->w_wc = c; 578 break; 579 } 580 a = qpatnext->w_at; 581 c = qpatnext->w_wc; 582 if (a == 0 && c == NOT) 583 ++qpatnext; 584 if (qpatnext->w_wc == EOS || 585 g_strchr(qpatnext+1, RBRACKET) == NULL) { 586 bufnext->w_at = 0; 587 (bufnext++)->w_wc = LBRACKET; 588 if (a == 0 && c == NOT) 589 --qpatnext; 590 break; 591 } 592 bufnext->w_at = M_QUOTE; 593 (bufnext++)->w_wc = M_SET; 594 if (a == 0 && c == NOT) { 595 bufnext->w_at = M_QUOTE; 596 (bufnext++)->w_wc = M_NOT; 597 } 598 a = qpatnext->w_at; 599 c = (qpatnext++)->w_wc; 600 do { 601 if (a == 0 && c == LBRACKET && 602 qpatnext->w_wc == COLON) { 603 do { 604 err = g_charclass(&qpatnext, 605 &bufnext); 606 if (err) 607 break; 608 a = qpatnext->w_at; 609 c = (qpatnext++)->w_wc; 610 } while (a == 0 && c == LBRACKET && 611 qpatnext->w_wc == COLON); 612 if (err == -1 && 613 !(pglob->gl_flags & GLOB_NOCHECK)) 614 return (GLOB_NOMATCH); 615 if (a == 0 && c == RBRACKET) 616 break; 617 } 618 bufnext->w_at = a; 619 (bufnext++)->w_wc = c; 620 if (qpatnext->w_at == 0 && 621 qpatnext->w_wc == RANGE) { 622 a = qpatnext[1].w_at; 623 c = qpatnext[1].w_wc; 624 if (qpatnext[1].w_at != 0 || 625 qpatnext[1].w_wc != RBRACKET) { 626 bufnext->w_at = M_QUOTE; 627 (bufnext++)->w_wc = M_RNG; 628 bufnext->w_at = a; 629 (bufnext++)->w_wc = c; 630 qpatnext += 2; 631 } 632 } 633 a = qpatnext->w_at; 634 c = (qpatnext++)->w_wc; 635 } while (a != 0 || c != RBRACKET); 636 pglob->gl_flags |= GLOB_MAGCHAR; 637 bufnext->w_at = M_QUOTE; 638 (bufnext++)->w_wc = M_END; 639 break; 640 case QUESTION: 641 if (a != 0) { 642 bufnext->w_at = a; 643 (bufnext++)->w_wc = c; 644 break; 645 } 646 pglob->gl_flags |= GLOB_MAGCHAR; 647 bufnext->w_at = M_QUOTE; 648 (bufnext++)->w_wc = M_ONE; 649 break; 650 case STAR: 651 if (a != 0) { 652 bufnext->w_at = a; 653 (bufnext++)->w_wc = c; 654 break; 655 } 656 pglob->gl_flags |= GLOB_MAGCHAR; 657 /* 658 * collapse adjacent stars to one, 659 * to avoid exponential behavior 660 */ 661 if (bufnext == patbuf || 662 bufnext[-1].w_at != M_QUOTE || 663 bufnext[-1].w_wc != M_ALL) { 664 bufnext->w_at = M_QUOTE; 665 (bufnext++)->w_wc = M_ALL; 666 } 667 break; 668 default: 669 bufnext->w_at = a; 670 (bufnext++)->w_wc = c; 671 break; 672 } 673 } 674 bufnext->w_at = 0; 675 bufnext->w_wc = EOS; 676 677 if ((err = glob1(patbuf, patbuf+PATH_MAX-1, pglob, limitp, errfunc)) 678 != 0) 679 return (err); 680 681 /* 682 * If there was no match we are going to append the pattern 683 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified 684 * and the pattern did not contain any magic characters 685 * GLOB_NOMAGIC is there just for compatibility with csh. 686 */ 687 if (pglob->gl_pathc == oldpathc) { 688 if ((pglob->gl_flags & GLOB_NOCHECK) || 689 ((pglob->gl_flags & GLOB_NOMAGIC) && 690 !(pglob->gl_flags & GLOB_MAGCHAR))) 691 return (globextend(pattern, pglob, limitp, NULL)); 692 else 693 return (GLOB_NOMATCH); 694 } 695 if (!(pglob->gl_flags & GLOB_NOSORT)) { 696 if ((pglob->gl_flags & GLOB_KEEPSTAT)) { 697 /* Keep the paths and stat info synced during sort */ 698 struct glob_path_stat *path_stat; 699 int i; 700 int n = pglob->gl_pathc - oldpathc; 701 int o = pglob->gl_offs + oldpathc; 702 703 if ((path_stat = calloc(n, sizeof (*path_stat))) == 704 NULL) 705 return (GLOB_NOSPACE); 706 for (i = 0; i < n; i++) { 707 path_stat[i].gps_path = pglob->gl_pathv[o + i]; 708 path_stat[i].gps_stat = pglob->gl_statv[o + i]; 709 } 710 qsort(path_stat, n, sizeof (*path_stat), compare_gps); 711 for (i = 0; i < n; i++) { 712 pglob->gl_pathv[o + i] = path_stat[i].gps_path; 713 pglob->gl_statv[o + i] = path_stat[i].gps_stat; 714 } 715 free(path_stat); 716 } else { 717 qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, 718 pglob->gl_pathc - oldpathc, sizeof (char *), 719 compare); 720 } 721 } 722 return (0); 723 } 724 725 static int 726 compare(const void *p, const void *q) 727 { 728 return (strcmp(*(char **)p, *(char **)q)); 729 } 730 731 static int 732 compare_gps(const void *_p, const void *_q) 733 { 734 const struct glob_path_stat *p = (const struct glob_path_stat *)_p; 735 const struct glob_path_stat *q = (const struct glob_path_stat *)_q; 736 737 return (strcmp(p->gps_path, q->gps_path)); 738 } 739 740 static int 741 glob1(wcat_t *pattern, wcat_t *pattern_last, glob_t *pglob, 742 struct glob_lim *limitp, int (*errfunc)(const char *, int)) 743 { 744 wcat_t pathbuf[PATH_MAX]; 745 746 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 747 if (pattern->w_wc == EOS) 748 return (0); 749 return (glob2(pathbuf, pathbuf+PATH_MAX-1, 750 pathbuf, pathbuf+PATH_MAX-1, 751 pattern, pattern_last, pglob, limitp, errfunc)); 752 } 753 754 /* 755 * The functions glob2 and glob3 are mutually recursive; there is one level 756 * of recursion for each segment in the pattern that contains one or more 757 * meta characters. 758 */ 759 static int 760 glob2(wcat_t *pathbuf, wcat_t *pathbuf_last, wcat_t *pathend, 761 wcat_t *pathend_last, wcat_t *pattern, wcat_t *pattern_last, 762 glob_t *pglob, struct glob_lim *limitp, int (*errfunc)(const char *, int)) 763 { 764 struct stat sb; 765 wcat_t *p, *q; 766 int anymeta; 767 768 /* 769 * Loop over pattern segments until end of pattern or until 770 * segment with meta character found. 771 */ 772 for (anymeta = 0; ; ) { 773 if (pattern->w_wc == EOS) { /* End of pattern? */ 774 pathend->w_at = 0; 775 pathend->w_wc = EOS; 776 777 if ((pglob->gl_flags & GLOB_LIMIT) && 778 limitp->glim_stat++ >= GLOB_LIMIT_STAT) { 779 errno = 0; 780 pathend->w_at = 0; 781 (pathend++)->w_wc = SEP; 782 pathend->w_at = 0; 783 pathend->w_wc = EOS; 784 return (GLOB_NOSPACE); 785 } 786 if (g_lstat(pathbuf, &sb, pglob)) 787 return (0); 788 789 if (((pglob->gl_flags & GLOB_MARK) && 790 (pathend[-1].w_at != 0 || 791 pathend[-1].w_wc != SEP)) && 792 (S_ISDIR(sb.st_mode) || 793 (S_ISLNK(sb.st_mode) && 794 (g_stat(pathbuf, &sb, pglob) == 0) && 795 S_ISDIR(sb.st_mode)))) { 796 if (pathend+1 > pathend_last) 797 return (GLOB_NOSPACE); 798 pathend->w_at = 0; 799 (pathend++)->w_wc = SEP; 800 pathend->w_at = 0; 801 pathend->w_wc = EOS; 802 } 803 ++pglob->gl_matchc; 804 return (globextend(pathbuf, pglob, limitp, &sb)); 805 } 806 807 /* Find end of next segment, copy tentatively to pathend. */ 808 q = pathend; 809 p = pattern; 810 while (p->w_wc != EOS && p->w_wc != SEP) { 811 if (ismeta(*p)) 812 anymeta = 1; 813 if (q+1 > pathend_last) 814 return (GLOB_NOSPACE); 815 *q++ = *p++; 816 } 817 818 if (!anymeta) { /* No expansion, do next segment. */ 819 pathend = q; 820 pattern = p; 821 while (pattern->w_wc == SEP) { 822 if (pathend+1 > pathend_last) 823 return (GLOB_NOSPACE); 824 *pathend++ = *pattern++; 825 } 826 } else { 827 /* Need expansion, recurse. */ 828 return (glob3(pathbuf, pathbuf_last, pathend, 829 pathend_last, pattern, p, pattern_last, 830 pglob, limitp, errfunc)); 831 } 832 } 833 /* NOTREACHED */ 834 } 835 836 static int 837 glob3(wcat_t *pathbuf, wcat_t *pathbuf_last, wcat_t *pathend, 838 wcat_t *pathend_last, wcat_t *pattern, wcat_t *restpattern, 839 wcat_t *restpattern_last, glob_t *pglob, struct glob_lim *limitp, 840 int (*errfunc)(const char *, int)) 841 { 842 struct dirent *dp; 843 DIR *dirp; 844 int err; 845 char buf[PATH_MAX]; 846 847 /* 848 * The readdirfunc declaration can't be prototyped, because it is 849 * assigned, below, to two functions which are prototyped in glob.h 850 * and dirent.h as taking pointers to differently typed opaque 851 * structures. 852 */ 853 struct dirent *(*readdirfunc)(void *); 854 855 if (pathend > pathend_last) 856 return (GLOB_NOSPACE); 857 pathend->w_at = 0; 858 pathend->w_wc = EOS; 859 errno = 0; 860 861 if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { 862 /* TODO: don't call for ENOENT or ENOTDIR? */ 863 if (errfunc) { 864 if (g_Ctoc(pathbuf, buf, sizeof (buf))) 865 return (GLOB_ABORTED); 866 if (errfunc(buf, errno) || 867 pglob->gl_flags & GLOB_ERR) 868 return (GLOB_ABORTED); 869 } 870 return (0); 871 } 872 873 err = 0; 874 875 /* Search directory for matching names. */ 876 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 877 readdirfunc = pglob->gl_readdir; 878 else 879 readdirfunc = (struct dirent *(*)(void *))readdir; 880 while ((dp = (*readdirfunc)(dirp))) { 881 char *sc; 882 wcat_t *dc; 883 int n; 884 int lensc; 885 wchar_t w; 886 887 if ((pglob->gl_flags & GLOB_LIMIT) && 888 limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) { 889 errno = 0; 890 pathend->w_at = 0; 891 (pathend++)->w_wc = SEP; 892 pathend->w_at = 0; 893 pathend->w_wc = EOS; 894 err = GLOB_NOSPACE; 895 break; 896 } 897 898 /* Initial DOT must be matched literally. */ 899 if (dp->d_name[0] == DOT && pattern->w_wc != DOT) 900 continue; 901 dc = pathend; 902 sc = dp->d_name; 903 lensc = strlen(sc) + 1; 904 while (dc < pathend_last) { 905 if ((n = mbtowc(&w, sc, lensc)) <= 0) { 906 sc += 1; 907 lensc -= 1; 908 dc->w_at = 0; 909 dc->w_wc = EOS; 910 } else { 911 sc += n; 912 lensc -= n; 913 dc->w_at = 0; 914 dc->w_wc = w; 915 } 916 dc++; 917 if (n <= 0) 918 break; 919 } 920 if (dc >= pathend_last) { 921 dc->w_at = 0; 922 dc->w_wc = EOS; 923 err = GLOB_NOSPACE; 924 break; 925 } 926 if (n < 0) { 927 err = GLOB_NOMATCH; 928 break; 929 } 930 931 if (!match(pathend, pattern, restpattern)) { 932 pathend->w_at = 0; 933 pathend->w_wc = EOS; 934 continue; 935 } 936 err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, 937 restpattern, restpattern_last, pglob, limitp, 938 errfunc); 939 if (err) 940 break; 941 } 942 943 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 944 (*pglob->gl_closedir)(dirp); 945 else 946 (void) closedir(dirp); 947 return (err); 948 } 949 950 951 /* 952 * Extend the gl_pathv member of a glob_t structure to accommodate a new item, 953 * add the new item, and update gl_pathc. Avoids excessive reallocation 954 * by doubling the number of elements each time. Uses gl_pathn to contain 955 * the number. 956 * 957 * Return 0 if new item added, error code if memory couldn't be allocated. 958 * 959 * Invariant of the glob_t structure: 960 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 961 * gl_pathv points to (gl_offs + gl_pathc + 1) items. 962 */ 963 static int 964 globextend(const wcat_t *path, glob_t *pglob, struct glob_lim *limitp, 965 struct stat *sb) 966 { 967 char **pathv; 968 ssize_t i; 969 size_t allocn, newn, len; 970 char *copy = NULL; 971 const wcat_t *p; 972 struct stat **statv; 973 char junk[MB_LEN_MAX]; 974 int n; 975 976 allocn = pglob->gl_pathn; 977 newn = 2 + pglob->gl_pathc + pglob->gl_offs; 978 979 if (newn <= allocn) { 980 pathv = pglob->gl_pathv; 981 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) 982 statv = pglob->gl_statv; 983 } else { 984 if (allocn == 0) 985 allocn = pglob->gl_offs + INITIAL; 986 allocn *= 2; 987 if (pglob->gl_offs >= INT_MAX || 988 pglob->gl_pathc >= INT_MAX || 989 allocn >= INT_MAX || 990 SIZE_MAX / sizeof (*pathv) <= allocn || 991 SIZE_MAX / sizeof (*statv) <= allocn) { 992 nospace: 993 for (i = pglob->gl_offs; i < (ssize_t)(newn - 2); 994 i++) { 995 if (pglob->gl_pathv && pglob->gl_pathv[i]) 996 free(pglob->gl_pathv[i]); 997 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 && 998 pglob->gl_statv && pglob->gl_statv[i]) 999 free(pglob->gl_statv[i]); 1000 } 1001 free(pglob->gl_pathv); 1002 pglob->gl_pathv = NULL; 1003 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { 1004 free(pglob->gl_statv); 1005 pglob->gl_statv = NULL; 1006 } 1007 return (GLOB_NOSPACE); 1008 } 1009 limitp->glim_malloc += allocn * sizeof (*pathv); 1010 pathv = reallocarray(pglob->gl_pathv, allocn, sizeof (*pathv)); 1011 if (pathv == NULL) 1012 goto nospace; 1013 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { 1014 limitp->glim_malloc += allocn * sizeof (*statv); 1015 statv = reallocarray(pglob->gl_statv, allocn, 1016 sizeof (*statv)); 1017 if (statv == NULL) 1018 goto nospace; 1019 } 1020 } 1021 pglob->gl_pathn = allocn; 1022 1023 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 1024 /* first time around -- clear initial gl_offs items */ 1025 pathv += pglob->gl_offs; 1026 for (i = pglob->gl_offs; --i >= 0; ) 1027 *--pathv = NULL; 1028 } 1029 pglob->gl_pathv = pathv; 1030 1031 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { 1032 if (pglob->gl_statv == NULL && pglob->gl_offs > 0) { 1033 /* first time around -- clear initial gl_offs items */ 1034 statv += pglob->gl_offs; 1035 for (i = pglob->gl_offs; --i >= 0; ) 1036 *--statv = NULL; 1037 } 1038 pglob->gl_statv = statv; 1039 if (sb == NULL) 1040 statv[pglob->gl_offs + pglob->gl_pathc] = NULL; 1041 else { 1042 limitp->glim_malloc += sizeof (**statv); 1043 if ((statv[pglob->gl_offs + pglob->gl_pathc] = 1044 malloc(sizeof (**statv))) == NULL) 1045 goto copy_error; 1046 (void) memcpy(statv[pglob->gl_offs + pglob->gl_pathc], 1047 sb, sizeof (*sb)); 1048 } 1049 statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL; 1050 } 1051 1052 len = MB_LEN_MAX; 1053 p = path; 1054 while ((n = wctomb(junk, p->w_wc)) > 0) { 1055 len += n; 1056 if ((p++)->w_wc == EOS) 1057 break; 1058 } 1059 if (n < 0) 1060 return (GLOB_NOMATCH); 1061 1062 limitp->glim_malloc += len; 1063 if ((copy = malloc(len)) != NULL) { 1064 if (g_Ctoc(path, copy, len)) { 1065 free(copy); 1066 return (GLOB_NOSPACE); 1067 } 1068 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 1069 } 1070 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 1071 1072 if ((pglob->gl_flags & GLOB_LIMIT) && 1073 limitp->glim_malloc >= GLOB_LIMIT_MALLOC) { 1074 errno = 0; 1075 return (GLOB_NOSPACE); 1076 } 1077 copy_error: 1078 return (copy == NULL ? GLOB_NOSPACE : 0); 1079 } 1080 1081 1082 /* 1083 * pattern matching function for filenames. Each occurrence of the * 1084 * pattern causes an iteration. 1085 * 1086 * Note, this function differs from the original as per the discussion 1087 * here: https://research.swtch.com/glob 1088 * 1089 * Basically we removed the recursion and made it use the algorithm 1090 * from Russ Cox to not go quadratic on cases like a file called 1091 * ("a" x 100) . "x" matched against a pattern like "a*a*a*a*a*a*a*y". 1092 */ 1093 static int 1094 match(wcat_t *name, wcat_t *pat, wcat_t *patend) 1095 { 1096 int ok, negate_range; 1097 wcat_t c, k; 1098 wcat_t *nextp = NULL; 1099 wcat_t *nextn = NULL; 1100 1101 loop: 1102 while (pat < patend) { 1103 c = *pat++; 1104 switch (c.w_wc) { 1105 case M_ALL: 1106 if (c.w_at != M_QUOTE) { 1107 k = *name++; 1108 if (k.w_at != c.w_at || k.w_wc != c.w_wc) 1109 return (0); 1110 break; 1111 } 1112 while (pat < patend && pat->w_at == M_QUOTE && 1113 pat->w_wc == M_ALL) 1114 pat++; /* eat consecutive '*' */ 1115 if (pat == patend) 1116 return (1); 1117 if (name->w_wc == EOS) 1118 return (0); 1119 nextn = name + 1; 1120 nextp = pat - 1; 1121 break; 1122 case M_ONE: 1123 if (c.w_at != M_QUOTE) { 1124 k = *name++; 1125 if (k.w_at != c.w_at || k.w_wc != c.w_wc) 1126 goto fail; 1127 break; 1128 } 1129 if ((name++)->w_wc == EOS) 1130 goto fail; 1131 break; 1132 case M_SET: 1133 if (c.w_at != M_QUOTE) { 1134 k = *name++; 1135 if (k.w_at != c.w_at || k.w_wc != c.w_wc) 1136 goto fail; 1137 break; 1138 } 1139 ok = 0; 1140 if ((k = *name++).w_wc == EOS) 1141 goto fail; 1142 if ((negate_range = (pat->w_at == M_QUOTE && 1143 pat->w_wc == M_NOT)) != 0) 1144 ++pat; 1145 while (((c = *pat++).w_at != M_QUOTE) || 1146 c.w_wc != M_END) { 1147 if (c.w_at == M_QUOTE && c.w_wc == M_CLASS) { 1148 wcat_t cc; 1149 1150 cc.w_at = pat->w_at; 1151 cc.w_wc = pat->w_wc; 1152 if (iswctype(k.w_wc, cc.w_wc)) 1153 ok = 1; 1154 ++pat; 1155 } 1156 if (pat->w_at == M_QUOTE && 1157 pat->w_wc == M_RNG) { 1158 if (c.w_wc <= k.w_wc && 1159 k.w_wc <= pat[1].w_wc) 1160 ok = 1; 1161 pat += 2; 1162 } else if (c.w_wc == k.w_wc) 1163 ok = 1; 1164 } 1165 if (ok == negate_range) 1166 goto fail; 1167 break; 1168 default: 1169 k = *name++; 1170 if (k.w_at != c.w_at || k.w_wc != c.w_wc) 1171 goto fail; 1172 break; 1173 } 1174 } 1175 if (name->w_wc == EOS) 1176 return (1); 1177 1178 fail: 1179 if (nextn) { 1180 pat = nextp; 1181 name = nextn; 1182 goto loop; 1183 } 1184 return (0); 1185 } 1186 1187 /* 1188 * Extended globfree() function, selected by #pragma redefine_extname 1189 * in glob.h with the external name _globfree_ext() . 1190 */ 1191 void 1192 _globfree_ext(glob_t *pglob) 1193 { 1194 int i; 1195 char **pp; 1196 1197 if (pglob->gl_pathv != NULL) { 1198 pp = pglob->gl_pathv + pglob->gl_offs; 1199 for (i = pglob->gl_pathc; i--; ++pp) 1200 free(*pp); 1201 free(pglob->gl_pathv); 1202 pglob->gl_pathv = NULL; 1203 } 1204 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 && 1205 pglob->gl_statv != NULL) { 1206 for (i = 0; i < pglob->gl_pathc; i++) { 1207 free(pglob->gl_statv[i]); 1208 } 1209 free(pglob->gl_statv); 1210 pglob->gl_statv = NULL; 1211 } 1212 } 1213 1214 static DIR * 1215 g_opendir(wcat_t *str, glob_t *pglob) 1216 { 1217 char buf[PATH_MAX]; 1218 1219 if (str->w_wc == EOS) 1220 (void) strlcpy(buf, ".", sizeof (buf)); 1221 else { 1222 if (g_Ctoc(str, buf, sizeof (buf))) 1223 return (NULL); 1224 } 1225 1226 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 1227 return ((*pglob->gl_opendir)(buf)); 1228 1229 return (opendir(buf)); 1230 } 1231 1232 static int 1233 g_lstat(wcat_t *fn, struct stat *sb, glob_t *pglob) 1234 { 1235 char buf[PATH_MAX]; 1236 1237 if (g_Ctoc(fn, buf, sizeof (buf))) 1238 return (-1); 1239 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 1240 return ((*pglob->gl_lstat)(buf, sb)); 1241 return (lstat(buf, sb)); 1242 } 1243 1244 static int 1245 g_stat(wcat_t *fn, struct stat *sb, glob_t *pglob) 1246 { 1247 char buf[PATH_MAX]; 1248 1249 if (g_Ctoc(fn, buf, sizeof (buf))) 1250 return (-1); 1251 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 1252 return ((*pglob->gl_stat)(buf, sb)); 1253 return (stat(buf, sb)); 1254 } 1255 1256 static wcat_t * 1257 g_strchr(const wcat_t *str, wchar_t ch) 1258 { 1259 do { 1260 if (str->w_at == 0 && str->w_wc == ch) 1261 return ((wcat_t *)str); 1262 } while ((str++)->w_wc != EOS); 1263 return (NULL); 1264 } 1265 1266 static int 1267 g_Ctoc(const wcat_t *str, char *buf, uint_t len) 1268 { 1269 int n; 1270 wchar_t w; 1271 1272 while (len >= MB_LEN_MAX) { 1273 w = (str++)->w_wc; 1274 if ((n = wctomb(buf, w)) > 0) { 1275 len -= n; 1276 buf += n; 1277 } 1278 if (n < 0) 1279 break; 1280 if (w == EOS) 1281 return (0); 1282 } 1283 return (1); 1284 } 1285 1286 #if defined(_LP64) || _FILE_OFFSET_BITS != 64 1287 1288 /* glob() function with legacy glob structure */ 1289 int 1290 old_glob(const char *pattern, int flags, int (*errfunc)(const char *, int), 1291 old_glob_t *pglob) 1292 { 1293 1294 glob_t gl; 1295 int rv; 1296 1297 flags &= GLOB_POSIX; 1298 1299 (void) memset(&gl, 0, sizeof (gl)); 1300 1301 /* 1302 * Copy all the members, old to new. There's 1303 * really no point in micro-optimizing the copying. 1304 * Other members are set to zero. 1305 */ 1306 gl.gl_pathc = pglob->gl_pathc; 1307 gl.gl_pathv = pglob->gl_pathv; 1308 gl.gl_offs = pglob->gl_offs; 1309 gl.gl_pathp = pglob->gl_pathp; 1310 gl.gl_pathn = pglob->gl_pathn; 1311 1312 rv = _glob_ext(pattern, flags, errfunc, &gl); 1313 1314 /* 1315 * Copy all the members, new to old. There's 1316 * really no point in micro-optimizing the copying. 1317 */ 1318 pglob->gl_pathc = gl.gl_pathc; 1319 pglob->gl_pathv = gl.gl_pathv; 1320 pglob->gl_offs = gl.gl_offs; 1321 pglob->gl_pathp = gl.gl_pathp; 1322 pglob->gl_pathn = gl.gl_pathn; 1323 1324 return (rv); 1325 } 1326 1327 /* globfree() function with legacy glob structure */ 1328 void 1329 old_globfree(old_glob_t *pglob) 1330 { 1331 glob_t gl; 1332 1333 (void) memset(&gl, 0, sizeof (gl)); 1334 1335 /* 1336 * Copy all the members, old to new. There's 1337 * really no point in micro-optimizing the copying. 1338 * Other members are set to zero. 1339 */ 1340 gl.gl_pathc = pglob->gl_pathc; 1341 gl.gl_pathv = pglob->gl_pathv; 1342 gl.gl_offs = pglob->gl_offs; 1343 gl.gl_pathp = pglob->gl_pathp; 1344 gl.gl_pathn = pglob->gl_pathn; 1345 1346 _globfree_ext(&gl); 1347 1348 /* 1349 * Copy all the members, new to old. There's 1350 * really no point in micro-optimizing the copying. 1351 */ 1352 pglob->gl_pathc = gl.gl_pathc; 1353 pglob->gl_pathv = gl.gl_pathv; 1354 pglob->gl_offs = gl.gl_offs; 1355 pglob->gl_pathp = gl.gl_pathp; 1356 pglob->gl_pathn = gl.gl_pathn; 1357 1358 } 1359 1360 #endif /* _LP64 || _FILE_OFFSET_BITS != 64 */