glob.c (181111) | glob.c (221420) |
---|---|
1/* $OpenBSD: glob.c,v 1.26 2005/11/28 17:50:12 deraadt Exp $ */ | 1/* $OpenBSD: glob.c,v 1.35 2011/01/12 01:53:14 djm 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 --- 18 unchanged lines hidden (view full) --- 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/* OPENBSD ORIGINAL: lib/libc/gen/glob.c */ 35 | 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 --- 18 unchanged lines hidden (view full) --- 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/* OPENBSD ORIGINAL: lib/libc/gen/glob.c */ 35 |
36#include "includes.h" 37 38#include <sys/types.h> 39#include <sys/stat.h> 40 41#include <dirent.h> 42#include <ctype.h> 43#include <errno.h> 44#include <pwd.h> 45#include <stdlib.h> 46#include <string.h> 47#include <unistd.h> 48 49#if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \ 50 !defined(GLOB_HAS_GL_MATCHC) || \ 51 !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ 52 defined(BROKEN_GLOB) 53 54static long 55get_arg_max(void) 56{ 57#ifdef ARG_MAX 58 return(ARG_MAX); 59#elif defined(HAVE_SYSCONF) && defined(_SC_ARG_MAX) 60 return(sysconf(_SC_ARG_MAX)); 61#else 62 return(256); /* XXX: arbitrary */ 63#endif 64} 65 | |
66/* 67 * glob(3) -- a superset of the one defined in POSIX 1003.2. 68 * 69 * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 70 * 71 * Optional extra services, controlled by flags not defined by POSIX: 72 * 73 * GLOB_QUOTE: --- 9 unchanged lines hidden (view full) --- 83 * GLOB_TILDE: 84 * expand ~user/foo to the /home/dir/of/user/foo 85 * GLOB_BRACE: 86 * expand {1,2}{a,b} to 1a 1b 2a 2b 87 * gl_matchc: 88 * Number of matches in the current invocation of glob. 89 */ 90 | 36/* 37 * glob(3) -- a superset of the one defined in POSIX 1003.2. 38 * 39 * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 40 * 41 * Optional extra services, controlled by flags not defined by POSIX: 42 * 43 * GLOB_QUOTE: --- 9 unchanged lines hidden (view full) --- 53 * GLOB_TILDE: 54 * expand ~user/foo to the /home/dir/of/user/foo 55 * GLOB_BRACE: 56 * expand {1,2}{a,b} to 1a 1b 2a 2b 57 * gl_matchc: 58 * Number of matches in the current invocation of glob. 59 */ 60 |
61#include "includes.h" |
|
91 | 62 |
63#include <sys/types.h> 64#include <sys/stat.h> 65 66#include <dirent.h> 67#include <ctype.h> 68#include <errno.h> 69#include <pwd.h> 70#include <stdlib.h> 71#include <string.h> 72#include <unistd.h> 73 74#if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \ 75 !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) || \ 76 !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ 77 defined(BROKEN_GLOB) 78 79#include "charclass.h" 80 |
|
92#define DOLLAR '$' 93#define DOT '.' 94#define EOS '\0' 95#define LBRACKET '[' 96#define NOT '!' 97#define QUESTION '?' 98#define QUOTE '\\' 99#define RANGE '-' 100#define RBRACKET ']' 101#define SEP '/' 102#define STAR '*' | 81#define DOLLAR '$' 82#define DOT '.' 83#define EOS '\0' 84#define LBRACKET '[' 85#define NOT '!' 86#define QUESTION '?' 87#define QUOTE '\\' 88#define RANGE '-' 89#define RBRACKET ']' 90#define SEP '/' 91#define STAR '*' |
103#undef TILDE /* Some platforms may already define it */ | |
104#define TILDE '~' 105#define UNDERSCORE '_' 106#define LBRACE '{' 107#define RBRACE '}' 108#define SLASH '/' 109#define COMMA ',' 110 111#ifndef DEBUG --- 20 unchanged lines hidden (view full) --- 132#define CHAR(c) ((Char)((c)&M_ASCII)) 133#define META(c) ((Char)((c)|M_QUOTE)) 134#define M_ALL META('*') 135#define M_END META(']') 136#define M_NOT META('!') 137#define M_ONE META('?') 138#define M_RNG META('-') 139#define M_SET META('[') | 92#define TILDE '~' 93#define UNDERSCORE '_' 94#define LBRACE '{' 95#define RBRACE '}' 96#define SLASH '/' 97#define COMMA ',' 98 99#ifndef DEBUG --- 20 unchanged lines hidden (view full) --- 120#define CHAR(c) ((Char)((c)&M_ASCII)) 121#define META(c) ((Char)((c)|M_QUOTE)) 122#define M_ALL META('*') 123#define M_END META(']') 124#define M_NOT META('!') 125#define M_ONE META('?') 126#define M_RNG META('-') 127#define M_SET META('[') |
128#define M_CLASS META(':') |
|
140#define ismeta(c) (((c)&M_QUOTE) != 0) 141 | 129#define ismeta(c) (((c)&M_QUOTE) != 0) 130 |
131#define GLOB_LIMIT_MALLOC 65536 132#define GLOB_LIMIT_STAT 128 133#define GLOB_LIMIT_READDIR 16384 |
|
142 | 134 |
135struct glob_lim { 136 size_t glim_malloc; 137 size_t glim_stat; 138 size_t glim_readdir; 139}; 140 |
|
143static int compare(const void *, const void *); 144static int g_Ctoc(const Char *, char *, u_int); 145static int g_lstat(Char *, struct stat *, glob_t *); 146static DIR *g_opendir(Char *, glob_t *); | 141static int compare(const void *, const void *); 142static int g_Ctoc(const Char *, char *, u_int); 143static int g_lstat(Char *, struct stat *, glob_t *); 144static DIR *g_opendir(Char *, glob_t *); |
147static Char *g_strchr(Char *, int); | 145static Char *g_strchr(const Char *, int); 146static int g_strncmp(const Char *, const char *, size_t); |
148static int g_stat(Char *, struct stat *, glob_t *); | 147static int g_stat(Char *, struct stat *, glob_t *); |
149static int glob0(const Char *, glob_t *); 150static int glob1(Char *, Char *, glob_t *, size_t *); | 148static int glob0(const Char *, glob_t *, struct glob_lim *); 149static int glob1(Char *, Char *, glob_t *, struct glob_lim *); |
151static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, | 150static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, |
152 glob_t *, size_t *); | 151 glob_t *, struct glob_lim *); |
153static int glob3(Char *, Char *, Char *, Char *, Char *, | 152static int glob3(Char *, Char *, Char *, Char *, Char *, |
154 Char *, Char *, glob_t *, size_t *); 155static int globextend(const Char *, glob_t *, size_t *); | 153 Char *, Char *, glob_t *, struct glob_lim *); 154static int globextend(const Char *, glob_t *, struct glob_lim *, 155 struct stat *); |
156static const Char * 157 globtilde(const Char *, Char *, size_t, glob_t *); | 156static const Char * 157 globtilde(const Char *, Char *, size_t, glob_t *); |
158static int globexp1(const Char *, glob_t *); 159static int globexp2(const Char *, const Char *, glob_t *, int *); | 158static int globexp1(const Char *, glob_t *, struct glob_lim *); 159static int globexp2(const Char *, const Char *, glob_t *, 160 struct glob_lim *); |
160static int match(Char *, Char *, Char *); 161#ifdef DEBUG 162static void qprintf(const char *, Char *); 163#endif 164 165int 166glob(const char *pattern, int flags, int (*errfunc)(const char *, int), 167 glob_t *pglob) 168{ 169 const u_char *patnext; 170 int c; 171 Char *bufnext, *bufend, patbuf[MAXPATHLEN]; | 161static int match(Char *, Char *, Char *); 162#ifdef DEBUG 163static void qprintf(const char *, Char *); 164#endif 165 166int 167glob(const char *pattern, int flags, int (*errfunc)(const char *, int), 168 glob_t *pglob) 169{ 170 const u_char *patnext; 171 int c; 172 Char *bufnext, *bufend, patbuf[MAXPATHLEN]; |
173 struct glob_lim limit = { 0, 0, 0 }; |
|
172 173 patnext = (u_char *) pattern; 174 if (!(flags & GLOB_APPEND)) { 175 pglob->gl_pathc = 0; 176 pglob->gl_pathv = NULL; | 174 175 patnext = (u_char *) pattern; 176 if (!(flags & GLOB_APPEND)) { 177 pglob->gl_pathc = 0; 178 pglob->gl_pathv = NULL; |
179 pglob->gl_statv = NULL; |
|
177 if (!(flags & GLOB_DOOFFS)) 178 pglob->gl_offs = 0; 179 } 180 pglob->gl_flags = flags & ~GLOB_MAGCHAR; 181 pglob->gl_errfunc = errfunc; 182 pglob->gl_matchc = 0; 183 | 180 if (!(flags & GLOB_DOOFFS)) 181 pglob->gl_offs = 0; 182 } 183 pglob->gl_flags = flags & ~GLOB_MAGCHAR; 184 pglob->gl_errfunc = errfunc; 185 pglob->gl_matchc = 0; 186 |
187 if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 || 188 pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX || 189 pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1) 190 return GLOB_NOSPACE; 191 |
|
184 bufnext = patbuf; 185 bufend = bufnext + MAXPATHLEN - 1; 186 if (flags & GLOB_NOESCAPE) 187 while (bufnext < bufend && (c = *patnext++) != EOS) 188 *bufnext++ = c; 189 else { 190 /* Protect the quoted characters. */ 191 while (bufnext < bufend && (c = *patnext++) != EOS) --- 4 unchanged lines hidden (view full) --- 196 } 197 *bufnext++ = c | M_PROTECT; 198 } else 199 *bufnext++ = c; 200 } 201 *bufnext = EOS; 202 203 if (flags & GLOB_BRACE) | 192 bufnext = patbuf; 193 bufend = bufnext + MAXPATHLEN - 1; 194 if (flags & GLOB_NOESCAPE) 195 while (bufnext < bufend && (c = *patnext++) != EOS) 196 *bufnext++ = c; 197 else { 198 /* Protect the quoted characters. */ 199 while (bufnext < bufend && (c = *patnext++) != EOS) --- 4 unchanged lines hidden (view full) --- 204 } 205 *bufnext++ = c | M_PROTECT; 206 } else 207 *bufnext++ = c; 208 } 209 *bufnext = EOS; 210 211 if (flags & GLOB_BRACE) |
204 return globexp1(patbuf, pglob); | 212 return globexp1(patbuf, pglob, &limit); |
205 else | 213 else |
206 return glob0(patbuf, pglob); | 214 return glob0(patbuf, pglob, &limit); |
207} 208 209/* 210 * Expand recursively a glob {} pattern. When there is no more expansion 211 * invoke the standard globbing routine to glob the rest of the magic 212 * characters 213 */ 214static int | 215} 216 217/* 218 * Expand recursively a glob {} pattern. When there is no more expansion 219 * invoke the standard globbing routine to glob the rest of the magic 220 * characters 221 */ 222static int |
215globexp1(const Char *pattern, glob_t *pglob) | 223globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) |
216{ 217 const Char* ptr = pattern; | 224{ 225 const Char* ptr = pattern; |
218 int rv; | |
219 220 /* Protect a single {}, for find(1), like csh */ 221 if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) | 226 227 /* Protect a single {}, for find(1), like csh */ 228 if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) |
222 return glob0(pattern, pglob); | 229 return glob0(pattern, pglob, limitp); |
223 | 230 |
224 while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) 225 if (!globexp2(ptr, pattern, pglob, &rv)) 226 return rv; | 231 if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) 232 return globexp2(ptr, pattern, pglob, limitp); |
227 | 233 |
228 return glob0(pattern, pglob); | 234 return glob0(pattern, pglob, limitp); |
229} 230 231 232/* 233 * Recursive brace globbing helper. Tries to expand a single brace. 234 * If it succeeds then it invokes globexp1 with the new pattern. 235 * If it fails then it tries to glob the rest of the pattern and returns. 236 */ 237static int | 235} 236 237 238/* 239 * Recursive brace globbing helper. Tries to expand a single brace. 240 * If it succeeds then it invokes globexp1 with the new pattern. 241 * If it fails then it tries to glob the rest of the pattern and returns. 242 */ 243static int |
238globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) | 244globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, 245 struct glob_lim *limitp) |
239{ | 246{ |
240 int i; | 247 int i, rv; |
241 Char *lm, *ls; 242 const Char *pe, *pm, *pl; 243 Char patbuf[MAXPATHLEN]; 244 245 /* copy part up to the brace */ 246 for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) 247 ; 248 *lm = EOS; --- 16 unchanged lines hidden (view full) --- 265 i++; 266 else if (*pe == RBRACE) { 267 if (i == 0) 268 break; 269 i--; 270 } 271 272 /* Non matching braces; just glob the pattern */ | 248 Char *lm, *ls; 249 const Char *pe, *pm, *pl; 250 Char patbuf[MAXPATHLEN]; 251 252 /* copy part up to the brace */ 253 for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) 254 ; 255 *lm = EOS; --- 16 unchanged lines hidden (view full) --- 272 i++; 273 else if (*pe == RBRACE) { 274 if (i == 0) 275 break; 276 i--; 277 } 278 279 /* Non matching braces; just glob the pattern */ |
273 if (i != 0 || *pe == EOS) { 274 *rv = glob0(patbuf, pglob); 275 return 0; 276 } | 280 if (i != 0 || *pe == EOS) 281 return glob0(patbuf, pglob, limitp); |
277 278 for (i = 0, pl = pm = ptr; pm <= pe; pm++) { 279 switch (*pm) { 280 case LBRACKET: 281 /* Ignore everything between [] */ 282 for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) 283 ; 284 if (*pm == EOS) { --- 29 unchanged lines hidden (view full) --- 314 */ 315 for (pl = pe + 1; (*lm++ = *pl++) != EOS; ) 316 ; 317 318 /* Expand the current pattern */ 319#ifdef DEBUG 320 qprintf("globexp2:", patbuf); 321#endif | 282 283 for (i = 0, pl = pm = ptr; pm <= pe; pm++) { 284 switch (*pm) { 285 case LBRACKET: 286 /* Ignore everything between [] */ 287 for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) 288 ; 289 if (*pm == EOS) { --- 29 unchanged lines hidden (view full) --- 319 */ 320 for (pl = pe + 1; (*lm++ = *pl++) != EOS; ) 321 ; 322 323 /* Expand the current pattern */ 324#ifdef DEBUG 325 qprintf("globexp2:", patbuf); 326#endif |
322 *rv = globexp1(patbuf, pglob); | 327 rv = globexp1(patbuf, pglob, limitp); 328 if (rv && rv != GLOB_NOMATCH) 329 return rv; |
323 324 /* move after the comma, to the next string */ 325 pl = pm + 1; 326 } 327 break; 328 329 default: 330 break; 331 } 332 } | 330 331 /* move after the comma, to the next string */ 332 pl = pm + 1; 333 } 334 break; 335 336 default: 337 break; 338 } 339 } |
333 *rv = 0; | |
334 return 0; 335} 336 337 338 339/* 340 * expand tilde from the passwd file. 341 */ --- 52 unchanged lines hidden (view full) --- 394 /* Append the rest of the pattern */ 395 while (b < eb && (*b++ = *p++) != EOS) 396 ; 397 *b = EOS; 398 399 return patbuf; 400} 401 | 340 return 0; 341} 342 343 344 345/* 346 * expand tilde from the passwd file. 347 */ --- 52 unchanged lines hidden (view full) --- 400 /* Append the rest of the pattern */ 401 while (b < eb && (*b++ = *p++) != EOS) 402 ; 403 *b = EOS; 404 405 return patbuf; 406} 407 |
408static int 409g_strncmp(const Char *s1, const char *s2, size_t n) 410{ 411 int rv = 0; |
|
402 | 412 |
413 while (n--) { 414 rv = *(Char *)s1 - *(const unsigned char *)s2++; 415 if (rv) 416 break; 417 if (*s1++ == '\0') 418 break; 419 } 420 return rv; 421} 422 423static int 424g_charclass(const Char **patternp, Char **bufnextp) 425{ 426 const Char *pattern = *patternp + 1; 427 Char *bufnext = *bufnextp; 428 const Char *colon; 429 struct cclass *cc; 430 size_t len; 431 432 if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']') 433 return 1; /* not a character class */ 434 435 len = (size_t)(colon - pattern); 436 for (cc = cclasses; cc->name != NULL; cc++) { 437 if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0') 438 break; 439 } 440 if (cc->name == NULL) 441 return -1; /* invalid character class */ 442 *bufnext++ = M_CLASS; 443 *bufnext++ = (Char)(cc - &cclasses[0]); 444 *bufnextp = bufnext; 445 *patternp += len + 3; 446 447 return 0; 448} 449 |
|
403/* 404 * The main glob() routine: compiles the pattern (optionally processing 405 * quotes), calls glob1() to do the real pattern matching, and finally 406 * sorts the list (unless unsorted operation is requested). Returns 0 407 * if things went well, nonzero if errors occurred. It is not an error 408 * to find no matches. 409 */ 410static int | 450/* 451 * The main glob() routine: compiles the pattern (optionally processing 452 * quotes), calls glob1() to do the real pattern matching, and finally 453 * sorts the list (unless unsorted operation is requested). Returns 0 454 * if things went well, nonzero if errors occurred. It is not an error 455 * to find no matches. 456 */ 457static int |
411glob0(const Char *pattern, glob_t *pglob) | 458glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) |
412{ 413 const Char *qpatnext; 414 int c, err, oldpathc; 415 Char *bufnext, patbuf[MAXPATHLEN]; | 459{ 460 const Char *qpatnext; 461 int c, err, oldpathc; 462 Char *bufnext, patbuf[MAXPATHLEN]; |
416 size_t limit = 0; | |
417 418 qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); 419 oldpathc = pglob->gl_pathc; 420 bufnext = patbuf; 421 422 /* We don't need to check for buffer overflow any more. */ 423 while ((c = *qpatnext++) != EOS) { 424 switch (c) { 425 case LBRACKET: 426 c = *qpatnext; 427 if (c == NOT) 428 ++qpatnext; 429 if (*qpatnext == EOS || | 463 464 qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); 465 oldpathc = pglob->gl_pathc; 466 bufnext = patbuf; 467 468 /* We don't need to check for buffer overflow any more. */ 469 while ((c = *qpatnext++) != EOS) { 470 switch (c) { 471 case LBRACKET: 472 c = *qpatnext; 473 if (c == NOT) 474 ++qpatnext; 475 if (*qpatnext == EOS || |
430 g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { | 476 g_strchr(qpatnext+1, RBRACKET) == NULL) { |
431 *bufnext++ = LBRACKET; 432 if (c == NOT) 433 --qpatnext; 434 break; 435 } 436 *bufnext++ = M_SET; 437 if (c == NOT) 438 *bufnext++ = M_NOT; 439 c = *qpatnext++; 440 do { | 477 *bufnext++ = LBRACKET; 478 if (c == NOT) 479 --qpatnext; 480 break; 481 } 482 *bufnext++ = M_SET; 483 if (c == NOT) 484 *bufnext++ = M_NOT; 485 c = *qpatnext++; 486 do { |
487 if (c == LBRACKET && *qpatnext == ':') { 488 do { 489 err = g_charclass(&qpatnext, 490 &bufnext); 491 if (err) 492 break; 493 c = *qpatnext++; 494 } while (c == LBRACKET && *qpatnext == ':'); 495 if (err == -1 && 496 !(pglob->gl_flags & GLOB_NOCHECK)) 497 return GLOB_NOMATCH; 498 if (c == RBRACKET) 499 break; 500 } |
|
441 *bufnext++ = CHAR(c); 442 if (*qpatnext == RANGE && 443 (c = qpatnext[1]) != RBRACKET) { 444 *bufnext++ = M_RNG; 445 *bufnext++ = CHAR(c); 446 qpatnext += 2; 447 } 448 } while ((c = *qpatnext++) != RBRACKET); --- 17 unchanged lines hidden (view full) --- 466 break; 467 } 468 } 469 *bufnext = EOS; 470#ifdef DEBUG 471 qprintf("glob0:", patbuf); 472#endif 473 | 501 *bufnext++ = CHAR(c); 502 if (*qpatnext == RANGE && 503 (c = qpatnext[1]) != RBRACKET) { 504 *bufnext++ = M_RNG; 505 *bufnext++ = CHAR(c); 506 qpatnext += 2; 507 } 508 } while ((c = *qpatnext++) != RBRACKET); --- 17 unchanged lines hidden (view full) --- 526 break; 527 } 528 } 529 *bufnext = EOS; 530#ifdef DEBUG 531 qprintf("glob0:", patbuf); 532#endif 533 |
474 if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) | 534 if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp)) != 0) |
475 return(err); 476 477 /* 478 * If there was no match we are going to append the pattern 479 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified 480 * and the pattern did not contain any magic characters 481 * GLOB_NOMAGIC is there just for compatibility with csh. 482 */ 483 if (pglob->gl_pathc == oldpathc) { 484 if ((pglob->gl_flags & GLOB_NOCHECK) || 485 ((pglob->gl_flags & GLOB_NOMAGIC) && 486 !(pglob->gl_flags & GLOB_MAGCHAR))) | 535 return(err); 536 537 /* 538 * If there was no match we are going to append the pattern 539 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified 540 * and the pattern did not contain any magic characters 541 * GLOB_NOMAGIC is there just for compatibility with csh. 542 */ 543 if (pglob->gl_pathc == oldpathc) { 544 if ((pglob->gl_flags & GLOB_NOCHECK) || 545 ((pglob->gl_flags & GLOB_NOMAGIC) && 546 !(pglob->gl_flags & GLOB_MAGCHAR))) |
487 return(globextend(pattern, pglob, &limit)); | 547 return(globextend(pattern, pglob, limitp, NULL)); |
488 else 489 return(GLOB_NOMATCH); 490 } 491 if (!(pglob->gl_flags & GLOB_NOSORT)) 492 qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, 493 pglob->gl_pathc - oldpathc, sizeof(char *), compare); 494 return(0); 495} 496 497static int 498compare(const void *p, const void *q) 499{ 500 return(strcmp(*(char **)p, *(char **)q)); 501} 502 503static int | 548 else 549 return(GLOB_NOMATCH); 550 } 551 if (!(pglob->gl_flags & GLOB_NOSORT)) 552 qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, 553 pglob->gl_pathc - oldpathc, sizeof(char *), compare); 554 return(0); 555} 556 557static int 558compare(const void *p, const void *q) 559{ 560 return(strcmp(*(char **)p, *(char **)q)); 561} 562 563static int |
504glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) | 564glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) |
505{ 506 Char pathbuf[MAXPATHLEN]; 507 508 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 509 if (*pattern == EOS) 510 return(0); 511 return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, 512 pathbuf, pathbuf+MAXPATHLEN-1, 513 pattern, pattern_last, pglob, limitp)); 514} 515 516/* 517 * The functions glob2 and glob3 are mutually recursive; there is one level 518 * of recursion for each segment in the pattern that contains one or more 519 * meta characters. 520 */ 521static int 522glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | 565{ 566 Char pathbuf[MAXPATHLEN]; 567 568 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 569 if (*pattern == EOS) 570 return(0); 571 return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, 572 pathbuf, pathbuf+MAXPATHLEN-1, 573 pattern, pattern_last, pglob, limitp)); 574} 575 576/* 577 * The functions glob2 and glob3 are mutually recursive; there is one level 578 * of recursion for each segment in the pattern that contains one or more 579 * meta characters. 580 */ 581static int 582glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, |
523 Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) | 583 Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) |
524{ 525 struct stat sb; 526 Char *p, *q; 527 int anymeta; 528 529 /* 530 * Loop over pattern segments until end of pattern or until 531 * segment with meta character found. 532 */ 533 for (anymeta = 0;;) { 534 if (*pattern == EOS) { /* End of pattern? */ 535 *pathend = EOS; 536 if (g_lstat(pathbuf, &sb, pglob)) 537 return(0); 538 | 584{ 585 struct stat sb; 586 Char *p, *q; 587 int anymeta; 588 589 /* 590 * Loop over pattern segments until end of pattern or until 591 * segment with meta character found. 592 */ 593 for (anymeta = 0;;) { 594 if (*pattern == EOS) { /* End of pattern? */ 595 *pathend = EOS; 596 if (g_lstat(pathbuf, &sb, pglob)) 597 return(0); 598 |
599 if ((pglob->gl_flags & GLOB_LIMIT) && 600 limitp->glim_stat++ >= GLOB_LIMIT_STAT) { 601 errno = 0; 602 *pathend++ = SEP; 603 *pathend = EOS; 604 return(GLOB_NOSPACE); 605 } 606 |
|
539 if (((pglob->gl_flags & GLOB_MARK) && 540 pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || 541 (S_ISLNK(sb.st_mode) && 542 (g_stat(pathbuf, &sb, pglob) == 0) && 543 S_ISDIR(sb.st_mode)))) { 544 if (pathend+1 > pathend_last) 545 return (1); 546 *pathend++ = SEP; 547 *pathend = EOS; 548 } 549 ++pglob->gl_matchc; | 607 if (((pglob->gl_flags & GLOB_MARK) && 608 pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || 609 (S_ISLNK(sb.st_mode) && 610 (g_stat(pathbuf, &sb, pglob) == 0) && 611 S_ISDIR(sb.st_mode)))) { 612 if (pathend+1 > pathend_last) 613 return (1); 614 *pathend++ = SEP; 615 *pathend = EOS; 616 } 617 ++pglob->gl_matchc; |
550 return(globextend(pathbuf, pglob, limitp)); | 618 return(globextend(pathbuf, pglob, limitp, &sb)); |
551 } 552 553 /* Find end of next segment, copy tentatively to pathend. */ 554 q = pathend; 555 p = pattern; 556 while (*p != EOS && *p != SEP) { 557 if (ismeta(*p)) 558 anymeta = 1; --- 17 unchanged lines hidden (view full) --- 576 pglob, limitp)); 577 } 578 /* NOTREACHED */ 579} 580 581static int 582glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, 583 Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, | 619 } 620 621 /* Find end of next segment, copy tentatively to pathend. */ 622 q = pathend; 623 p = pattern; 624 while (*p != EOS && *p != SEP) { 625 if (ismeta(*p)) 626 anymeta = 1; --- 17 unchanged lines hidden (view full) --- 644 pglob, limitp)); 645 } 646 /* NOTREACHED */ 647} 648 649static int 650glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, 651 Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, |
584 size_t *limitp) | 652 struct glob_lim *limitp) |
585{ 586 struct dirent *dp; 587 DIR *dirp; 588 int err; 589 char buf[MAXPATHLEN]; 590 591 /* 592 * The readdirfunc declaration can't be prototyped, because it is --- 26 unchanged lines hidden (view full) --- 619 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 620 readdirfunc = pglob->gl_readdir; 621 else 622 readdirfunc = (struct dirent *(*)(void *))readdir; 623 while ((dp = (*readdirfunc)(dirp))) { 624 u_char *sc; 625 Char *dc; 626 | 653{ 654 struct dirent *dp; 655 DIR *dirp; 656 int err; 657 char buf[MAXPATHLEN]; 658 659 /* 660 * The readdirfunc declaration can't be prototyped, because it is --- 26 unchanged lines hidden (view full) --- 687 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 688 readdirfunc = pglob->gl_readdir; 689 else 690 readdirfunc = (struct dirent *(*)(void *))readdir; 691 while ((dp = (*readdirfunc)(dirp))) { 692 u_char *sc; 693 Char *dc; 694 |
695 if ((pglob->gl_flags & GLOB_LIMIT) && 696 limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) { 697 errno = 0; 698 *pathend++ = SEP; 699 *pathend = EOS; 700 return(GLOB_NOSPACE); 701 } 702 |
|
627 /* Initial DOT must be matched literally. */ 628 if (dp->d_name[0] == DOT && *pattern != DOT) 629 continue; 630 dc = pathend; 631 sc = (u_char *) dp->d_name; 632 while (dc < pathend_last && (*dc++ = *sc++) != EOS) 633 ; 634 if (dc >= pathend_last) { --- 30 unchanged lines hidden (view full) --- 665 * 666 * Return 0 if new item added, error code if memory couldn't be allocated. 667 * 668 * Invariant of the glob_t structure: 669 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 670 * gl_pathv points to (gl_offs + gl_pathc + 1) items. 671 */ 672static int | 703 /* Initial DOT must be matched literally. */ 704 if (dp->d_name[0] == DOT && *pattern != DOT) 705 continue; 706 dc = pathend; 707 sc = (u_char *) dp->d_name; 708 while (dc < pathend_last && (*dc++ = *sc++) != EOS) 709 ; 710 if (dc >= pathend_last) { --- 30 unchanged lines hidden (view full) --- 741 * 742 * Return 0 if new item added, error code if memory couldn't be allocated. 743 * 744 * Invariant of the glob_t structure: 745 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 746 * gl_pathv points to (gl_offs + gl_pathc + 1) items. 747 */ 748static int |
673globextend(const Char *path, glob_t *pglob, size_t *limitp) | 749globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, 750 struct stat *sb) |
674{ 675 char **pathv; | 751{ 752 char **pathv; |
676 int i; 677 u_int newsize, len; 678 char *copy; | 753 ssize_t i; 754 size_t newn, len; 755 char *copy = NULL; |
679 const Char *p; | 756 const Char *p; |
757 struct stat **statv; |
|
680 | 758 |
681 newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); 682 pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : 683 malloc(newsize); 684 if (pathv == NULL) { | 759 newn = 2 + pglob->gl_pathc + pglob->gl_offs; 760 if (pglob->gl_offs >= INT_MAX || 761 pglob->gl_pathc >= INT_MAX || 762 newn >= INT_MAX || 763 SIZE_MAX / sizeof(*pathv) <= newn || 764 SIZE_MAX / sizeof(*statv) <= newn) { 765 nospace: 766 for (i = pglob->gl_offs; i < (ssize_t)(newn - 2); i++) { 767 if (pglob->gl_pathv && pglob->gl_pathv[i]) 768 free(pglob->gl_pathv[i]); 769 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 && 770 pglob->gl_pathv && pglob->gl_pathv[i]) 771 free(pglob->gl_statv[i]); 772 } |
685 if (pglob->gl_pathv) { 686 free(pglob->gl_pathv); 687 pglob->gl_pathv = NULL; 688 } | 773 if (pglob->gl_pathv) { 774 free(pglob->gl_pathv); 775 pglob->gl_pathv = NULL; 776 } |
777 if (pglob->gl_statv) { 778 free(pglob->gl_statv); 779 pglob->gl_statv = NULL; 780 } |
|
689 return(GLOB_NOSPACE); 690 } 691 | 781 return(GLOB_NOSPACE); 782 } 783 |
784 pathv = realloc(pglob->gl_pathv, newn * sizeof(*pathv)); 785 if (pathv == NULL) 786 goto nospace; |
|
692 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 693 /* first time around -- clear initial gl_offs items */ 694 pathv += pglob->gl_offs; 695 for (i = pglob->gl_offs; --i >= 0; ) 696 *--pathv = NULL; 697 } 698 pglob->gl_pathv = pathv; 699 | 787 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 788 /* first time around -- clear initial gl_offs items */ 789 pathv += pglob->gl_offs; 790 for (i = pglob->gl_offs; --i >= 0; ) 791 *--pathv = NULL; 792 } 793 pglob->gl_pathv = pathv; 794 |
795 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { 796 statv = realloc(pglob->gl_statv, newn * sizeof(*statv)); 797 if (statv == NULL) 798 goto nospace; 799 if (pglob->gl_statv == NULL && pglob->gl_offs > 0) { 800 /* first time around -- clear initial gl_offs items */ 801 statv += pglob->gl_offs; 802 for (i = pglob->gl_offs; --i >= 0; ) 803 *--statv = NULL; 804 } 805 pglob->gl_statv = statv; 806 if (sb == NULL) 807 statv[pglob->gl_offs + pglob->gl_pathc] = NULL; 808 else { 809 limitp->glim_malloc += sizeof(**statv); 810 if ((pglob->gl_flags & GLOB_LIMIT) && 811 limitp->glim_malloc >= GLOB_LIMIT_MALLOC) { 812 errno = 0; 813 return(GLOB_NOSPACE); 814 } 815 if ((statv[pglob->gl_offs + pglob->gl_pathc] = 816 malloc(sizeof(**statv))) == NULL) 817 goto copy_error; 818 memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb, 819 sizeof(*sb)); 820 } 821 statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL; 822 } 823 |
|
700 for (p = path; *p++;) 701 ; 702 len = (size_t)(p - path); | 824 for (p = path; *p++;) 825 ; 826 len = (size_t)(p - path); |
703 *limitp += len; | 827 limitp->glim_malloc += len; |
704 if ((copy = malloc(len)) != NULL) { 705 if (g_Ctoc(path, copy, len)) { 706 free(copy); 707 return(GLOB_NOSPACE); 708 } 709 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 710 } 711 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 712 713 if ((pglob->gl_flags & GLOB_LIMIT) && | 828 if ((copy = malloc(len)) != NULL) { 829 if (g_Ctoc(path, copy, len)) { 830 free(copy); 831 return(GLOB_NOSPACE); 832 } 833 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 834 } 835 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 836 837 if ((pglob->gl_flags & GLOB_LIMIT) && |
714 newsize + *limitp >= (u_int) get_arg_max()) { | 838 (newn * sizeof(*pathv)) + limitp->glim_malloc > 839 GLOB_LIMIT_MALLOC) { |
715 errno = 0; 716 return(GLOB_NOSPACE); 717 } | 840 errno = 0; 841 return(GLOB_NOSPACE); 842 } |
718 | 843 copy_error: |
719 return(copy == NULL ? GLOB_NOSPACE : 0); 720} 721 722 723/* 724 * pattern matching function for filenames. Each occurrence of the * 725 * pattern causes a recursion level. 726 */ --- 19 unchanged lines hidden (view full) --- 746 return(0); 747 break; 748 case M_SET: 749 ok = 0; 750 if ((k = *name++) == EOS) 751 return(0); 752 if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) 753 ++pat; | 844 return(copy == NULL ? GLOB_NOSPACE : 0); 845} 846 847 848/* 849 * pattern matching function for filenames. Each occurrence of the * 850 * pattern causes a recursion level. 851 */ --- 19 unchanged lines hidden (view full) --- 871 return(0); 872 break; 873 case M_SET: 874 ok = 0; 875 if ((k = *name++) == EOS) 876 return(0); 877 if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) 878 ++pat; |
754 while (((c = *pat++) & M_MASK) != M_END) | 879 while (((c = *pat++) & M_MASK) != M_END) { 880 if ((c & M_MASK) == M_CLASS) { 881 Char idx = *pat & M_MASK; 882 if (idx < NCCLASSES && 883 cclasses[idx].isctype(k)) 884 ok = 1; 885 ++pat; 886 } |
755 if ((*pat & M_MASK) == M_RNG) { 756 if (c <= k && k <= pat[1]) 757 ok = 1; 758 pat += 2; 759 } else if (c == k) 760 ok = 1; | 887 if ((*pat & M_MASK) == M_RNG) { 888 if (c <= k && k <= pat[1]) 889 ok = 1; 890 pat += 2; 891 } else if (c == k) 892 ok = 1; |
893 } |
|
761 if (ok == negate_range) 762 return(0); 763 break; 764 default: 765 if (*name++ != c) 766 return(0); 767 break; 768 } --- 11 unchanged lines hidden (view full) --- 780 if (pglob->gl_pathv != NULL) { 781 pp = pglob->gl_pathv + pglob->gl_offs; 782 for (i = pglob->gl_pathc; i--; ++pp) 783 if (*pp) 784 free(*pp); 785 free(pglob->gl_pathv); 786 pglob->gl_pathv = NULL; 787 } | 894 if (ok == negate_range) 895 return(0); 896 break; 897 default: 898 if (*name++ != c) 899 return(0); 900 break; 901 } --- 11 unchanged lines hidden (view full) --- 913 if (pglob->gl_pathv != NULL) { 914 pp = pglob->gl_pathv + pglob->gl_offs; 915 for (i = pglob->gl_pathc; i--; ++pp) 916 if (*pp) 917 free(*pp); 918 free(pglob->gl_pathv); 919 pglob->gl_pathv = NULL; 920 } |
921 if (pglob->gl_statv != NULL) { 922 for (i = 0; i < pglob->gl_pathc; i++) { 923 if (pglob->gl_statv[i] != NULL) 924 free(pglob->gl_statv[i]); 925 } 926 free(pglob->gl_statv); 927 pglob->gl_statv = NULL; 928 } |
|
788} 789 790static DIR * 791g_opendir(Char *str, glob_t *pglob) 792{ 793 char buf[MAXPATHLEN]; 794 795 if (!*str) --- 29 unchanged lines hidden (view full) --- 825 if (g_Ctoc(fn, buf, sizeof(buf))) 826 return(-1); 827 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 828 return((*pglob->gl_stat)(buf, sb)); 829 return(stat(buf, sb)); 830} 831 832static Char * | 929} 930 931static DIR * 932g_opendir(Char *str, glob_t *pglob) 933{ 934 char buf[MAXPATHLEN]; 935 936 if (!*str) --- 29 unchanged lines hidden (view full) --- 966 if (g_Ctoc(fn, buf, sizeof(buf))) 967 return(-1); 968 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 969 return((*pglob->gl_stat)(buf, sb)); 970 return(stat(buf, sb)); 971} 972 973static Char * |
833g_strchr(Char *str, int ch) | 974g_strchr(const Char *str, int ch) |
834{ 835 do { 836 if (*str == ch) | 975{ 976 do { 977 if (*str == ch) |
837 return (str); | 978 return ((Char *)str); |
838 } while (*str++); 839 return (NULL); 840} 841 842static int 843g_Ctoc(const Char *str, char *buf, u_int len) 844{ 845 --- 19 unchanged lines hidden (view full) --- 865 (void)printf("\n"); 866 for (p = s; *p; p++) 867 (void)printf("%c", ismeta(*p) ? '_' : ' '); 868 (void)printf("\n"); 869} 870#endif 871 872#endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || | 979 } while (*str++); 980 return (NULL); 981} 982 983static int 984g_Ctoc(const Char *str, char *buf, u_int len) 985{ 986 --- 19 unchanged lines hidden (view full) --- 1006 (void)printf("\n"); 1007 for (p = s; *p; p++) 1008 (void)printf("%c", ismeta(*p) ? '_' : ' '); 1009 (void)printf("\n"); 1010} 1011#endif 1012 1013#endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || |
873 !defined(GLOB_HAS_GL_MATCHC) */ 874 | 1014 !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) */ |