| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: glob.c,v 1.23.4.1 2010/07/19 18:14:08 riz Exp $ */ | | 1 | /* $NetBSD: glob.c,v 1.23.4.1.2.1 2011/04/24 15:41:23 riz Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1989, 1993 | | 4 | * Copyright (c) 1989, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Guido van Rossum. | | 8 | * Guido van Rossum. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -27,27 +27,27 @@ | | | @@ -27,27 +27,27 @@ |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | #if defined(LIBC_SCCS) && !defined(lint) | | 36 | #if defined(LIBC_SCCS) && !defined(lint) |
37 | #if 0 | | 37 | #if 0 |
38 | static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; | | 38 | static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; |
39 | #else | | 39 | #else |
40 | __RCSID("$NetBSD: glob.c,v 1.23.4.1 2010/07/19 18:14:08 riz Exp $"); | | 40 | __RCSID("$NetBSD: glob.c,v 1.23.4.1.2.1 2011/04/24 15:41:23 riz Exp $"); |
41 | #endif | | 41 | #endif |
42 | #endif /* LIBC_SCCS and not lint */ | | 42 | #endif /* LIBC_SCCS and not lint */ |
43 | | | 43 | |
44 | /* | | 44 | /* |
45 | * glob(3) -- a superset of the one defined in POSIX 1003.2. | | 45 | * glob(3) -- a superset of the one defined in POSIX 1003.2. |
46 | * | | 46 | * |
47 | * The [!...] convention to negate a range is supported (SysV, Posix, ksh). | | 47 | * The [!...] convention to negate a range is supported (SysV, Posix, ksh). |
48 | * | | 48 | * |
49 | * Optional extra services, controlled by flags not defined by POSIX: | | 49 | * Optional extra services, controlled by flags not defined by POSIX: |
50 | * | | 50 | * |
51 | * GLOB_MAGCHAR: | | 51 | * GLOB_MAGCHAR: |
52 | * Set in gl_flags if pattern contained a globbing character. | | 52 | * Set in gl_flags if pattern contained a globbing character. |
53 | * GLOB_NOMAGIC: | | 53 | * GLOB_NOMAGIC: |
| @@ -77,33 +77,38 @@ __RCSID("$NetBSD: glob.c,v 1.23.4.1 2010 | | | @@ -77,33 +77,38 @@ __RCSID("$NetBSD: glob.c,v 1.23.4.1 2010 |
77 | #include <errno.h> | | 77 | #include <errno.h> |
78 | #include <glob.h> | | 78 | #include <glob.h> |
79 | #include <pwd.h> | | 79 | #include <pwd.h> |
80 | #include <stdio.h> | | 80 | #include <stdio.h> |
81 | #include <stddef.h> | | 81 | #include <stddef.h> |
82 | #include <stdlib.h> | | 82 | #include <stdlib.h> |
83 | #include <string.h> | | 83 | #include <string.h> |
84 | #include <unistd.h> | | 84 | #include <unistd.h> |
85 | | | 85 | |
86 | #ifdef HAVE_NBTOOL_CONFIG_H | | 86 | #ifdef HAVE_NBTOOL_CONFIG_H |
87 | #define NO_GETPW_R | | 87 | #define NO_GETPW_R |
88 | #endif | | 88 | #endif |
89 | | | 89 | |
90 | #define GLOB_LIMIT_MALLOC 65536 | | 90 | #define GLOB_LIMIT_STRING 65536 /* number of readdirs */ |
91 | #define GLOB_LIMIT_STAT 128 | | 91 | #define GLOB_LIMIT_STAT 128 /* number of stat system calls */ |
92 | #define GLOB_LIMIT_READDIR 16384 | | 92 | #define GLOB_LIMIT_READDIR 16384 /* total buffer size of path strings */ |
93 | | | 93 | #define GLOB_LIMIT_PATH 1024 /* number of path elements */ |
94 | #define GLOB_INDEX_MALLOC 0 | | 94 | #define GLOB_LIMIT_BRACE 128 /* Number of brace calls */ |
95 | #define GLOB_INDEX_STAT 1 | | 95 | |
96 | #define GLOB_INDEX_READDIR 2 | | 96 | struct glob_limit { |
| | | 97 | size_t l_string; |
| | | 98 | size_t l_stat; |
| | | 99 | size_t l_readdir; |
| | | 100 | size_t l_brace; |
| | | 101 | }; |
97 | | | 102 | |
98 | /* | | 103 | /* |
99 | * XXX: For NetBSD 1.4.x compatibility. (kill me l8r) | | 104 | * XXX: For NetBSD 1.4.x compatibility. (kill me l8r) |
100 | */ | | 105 | */ |
101 | #ifndef _DIAGASSERT | | 106 | #ifndef _DIAGASSERT |
102 | #define _DIAGASSERT(a) | | 107 | #define _DIAGASSERT(a) |
103 | #endif | | 108 | #endif |
104 | | | 109 | |
105 | #define DOLLAR '$' | | 110 | #define DOLLAR '$' |
106 | #define DOT '.' | | 111 | #define DOT '.' |
107 | #define EOS '\0' | | 112 | #define EOS '\0' |
108 | #define LBRACKET '[' | | 113 | #define LBRACKET '[' |
109 | #define NOT '!' | | 114 | #define NOT '!' |
| @@ -148,51 +153,50 @@ typedef char Char; | | | @@ -148,51 +153,50 @@ typedef char Char; |
148 | #define M_NOT META('!') | | 153 | #define M_NOT META('!') |
149 | #define M_ONE META('?') | | 154 | #define M_ONE META('?') |
150 | #define M_RNG META('-') | | 155 | #define M_RNG META('-') |
151 | #define M_SET META('[') | | 156 | #define M_SET META('[') |
152 | #define ismeta(c) (((c)&M_QUOTE) != 0) | | 157 | #define ismeta(c) (((c)&M_QUOTE) != 0) |
153 | | | 158 | |
154 | | | 159 | |
155 | static int compare(const void *, const void *); | | 160 | static int compare(const void *, const void *); |
156 | static int g_Ctoc(const Char *, char *, size_t); | | 161 | static int g_Ctoc(const Char *, char *, size_t); |
157 | static int g_lstat(Char *, __gl_stat_t *, glob_t *); | | 162 | static int g_lstat(Char *, __gl_stat_t *, glob_t *); |
158 | static DIR *g_opendir(Char *, glob_t *); | | 163 | static DIR *g_opendir(Char *, glob_t *); |
159 | static Char *g_strchr(const Char *, int); | | 164 | static Char *g_strchr(const Char *, int); |
160 | static int g_stat(Char *, __gl_stat_t *, glob_t *); | | 165 | static int g_stat(Char *, __gl_stat_t *, glob_t *); |
161 | static int glob0(const Char *, glob_t *, size_t *); | | 166 | static int glob0(const Char *, glob_t *, struct glob_limit *); |
162 | static int glob1(Char *, glob_t *, size_t *); | | 167 | static int glob1(Char *, glob_t *, struct glob_limit *); |
163 | static int glob2(Char *, Char *, Char *, Char *, glob_t *, | | 168 | static int glob2(Char *, Char *, Char *, const Char *, glob_t *, |
164 | size_t *); | | 169 | struct glob_limit *); |
165 | static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, | | 170 | static int glob3(Char *, Char *, Char *, const Char *, const Char *, |
166 | size_t *); | | 171 | glob_t *, struct glob_limit *); |
167 | static int globextend(const Char *, glob_t *, size_t *); | | 172 | static int globextend(const Char *, glob_t *, struct glob_limit *); |
168 | static const Char *globtilde(const Char *, Char *, size_t, glob_t *); | | 173 | static const Char *globtilde(const Char *, Char *, size_t, glob_t *); |
169 | static int globexp1(const Char *, glob_t *, size_t *); | | 174 | static int globexp1(const Char *, glob_t *, struct glob_limit *); |
170 | static int globexp2(const Char *, const Char *, glob_t *, int *, | | 175 | static int globexp2(const Char *, const Char *, glob_t *, int *, |
171 | size_t *); | | 176 | struct glob_limit *); |
172 | static int match(Char *, Char *, Char *); | | 177 | static int match(const Char *, const Char *, const Char *); |
173 | #ifdef DEBUG | | 178 | #ifdef DEBUG |
174 | static void qprintf(const char *, Char *); | | 179 | static void qprintf(const char *, Char *); |
175 | #endif | | 180 | #endif |
176 | | | 181 | |
177 | int | | 182 | int |
178 | glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | | 183 | glob(const char *pattern, int flags, int (*errfunc)(const char *, int), |
179 | glob_t *pglob) | | 184 | glob_t *pglob) |
180 | { | | 185 | { |
181 | const u_char *patnext; | | 186 | const u_char *patnext; |
182 | int c; | | 187 | int c; |
183 | Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; | | 188 | Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; |
184 | /* 0 = malloc(), 1 = stat(), 2 = readdir() */ | | 189 | struct glob_limit limit = { 0, 0, 0, 0 }; |
185 | size_t limit[] = { 0, 0, 0 }; | | | |
186 | | | 190 | |
187 | _DIAGASSERT(pattern != NULL); | | 191 | _DIAGASSERT(pattern != NULL); |
188 | | | 192 | |
189 | patnext = (const u_char *) pattern; | | 193 | patnext = (const u_char *) pattern; |
190 | if (!(flags & GLOB_APPEND)) { | | 194 | if (!(flags & GLOB_APPEND)) { |
191 | pglob->gl_pathc = 0; | | 195 | pglob->gl_pathc = 0; |
192 | pglob->gl_pathv = NULL; | | 196 | pglob->gl_pathv = NULL; |
193 | if (!(flags & GLOB_DOOFFS)) | | 197 | if (!(flags & GLOB_DOOFFS)) |
194 | pglob->gl_offs = 0; | | 198 | pglob->gl_offs = 0; |
195 | } | | 199 | } |
196 | pglob->gl_flags = flags & ~GLOB_MAGCHAR; | | 200 | pglob->gl_flags = flags & ~GLOB_MAGCHAR; |
197 | pglob->gl_errfunc = errfunc; | | 201 | pglob->gl_errfunc = errfunc; |
198 | pglob->gl_matchc = 0; | | 202 | pglob->gl_matchc = 0; |
| @@ -208,65 +212,71 @@ glob(const char *pattern, int flags, int | | | @@ -208,65 +212,71 @@ glob(const char *pattern, int flags, int |
208 | if (c == QUOTE) { | | 212 | if (c == QUOTE) { |
209 | if ((c = *patnext++) == EOS) { | | 213 | if ((c = *patnext++) == EOS) { |
210 | c = QUOTE; | | 214 | c = QUOTE; |
211 | --patnext; | | 215 | --patnext; |
212 | } | | 216 | } |
213 | *bufnext++ = c | M_PROTECT; | | 217 | *bufnext++ = c | M_PROTECT; |
214 | } | | 218 | } |
215 | else | | 219 | else |
216 | *bufnext++ = c; | | 220 | *bufnext++ = c; |
217 | } | | 221 | } |
218 | *bufnext = EOS; | | 222 | *bufnext = EOS; |
219 | | | 223 | |
220 | if (flags & GLOB_BRACE) | | 224 | if (flags & GLOB_BRACE) |
221 | return globexp1(patbuf, pglob, limit); | | 225 | return globexp1(patbuf, pglob, &limit); |
222 | else | | 226 | else |
223 | return glob0(patbuf, pglob, limit); | | 227 | return glob0(patbuf, pglob, &limit); |
224 | } | | 228 | } |
225 | | | 229 | |
226 | /* | | 230 | /* |
227 | * Expand recursively a glob {} pattern. When there is no more expansion | | 231 | * Expand recursively a glob {} pattern. When there is no more expansion |
228 | * invoke the standard globbing routine to glob the rest of the magic | | 232 | * invoke the standard globbing routine to glob the rest of the magic |
229 | * characters | | 233 | * characters |
230 | */ | | 234 | */ |
231 | static int | | 235 | static int |
232 | globexp1(const Char *pattern, glob_t *pglob, size_t *limit) | | 236 | globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit) |
233 | { | | 237 | { |
234 | const Char* ptr = pattern; | | 238 | const Char* ptr = pattern; |
235 | int rv; | | 239 | int rv; |
236 | | | 240 | |
237 | _DIAGASSERT(pattern != NULL); | | 241 | _DIAGASSERT(pattern != NULL); |
238 | _DIAGASSERT(pglob != NULL); | | 242 | _DIAGASSERT(pglob != NULL); |
239 | | | 243 | |
| | | 244 | if ((pglob->gl_flags & GLOB_LIMIT) && |
| | | 245 | limit->l_brace++ >= GLOB_LIMIT_BRACE) { |
| | | 246 | errno = 0; |
| | | 247 | return GLOB_NOSPACE; |
| | | 248 | } |
| | | 249 | |
240 | /* Protect a single {}, for find(1), like csh */ | | 250 | /* Protect a single {}, for find(1), like csh */ |
241 | if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) | | 251 | if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) |
242 | return glob0(pattern, pglob, limit); | | 252 | return glob0(pattern, pglob, limit); |
243 | | | 253 | |
244 | while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) | | 254 | while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) |
245 | if (!globexp2(ptr, pattern, pglob, &rv, limit)) | | 255 | if (!globexp2(ptr, pattern, pglob, &rv, limit)) |
246 | return rv; | | 256 | return rv; |
247 | | | 257 | |
248 | return glob0(pattern, pglob, limit); | | 258 | return glob0(pattern, pglob, limit); |
249 | } | | 259 | } |
250 | | | 260 | |
251 | | | 261 | |
252 | /* | | 262 | /* |
253 | * Recursive brace globbing helper. Tries to expand a single brace. | | 263 | * Recursive brace globbing helper. Tries to expand a single brace. |
254 | * If it succeeds then it invokes globexp1 with the new pattern. | | 264 | * If it succeeds then it invokes globexp1 with the new pattern. |
255 | * If it fails then it tries to glob the rest of the pattern and returns. | | 265 | * If it fails then it tries to glob the rest of the pattern and returns. |
256 | */ | | 266 | */ |
257 | static int | | 267 | static int |
258 | globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, | | 268 | globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, |
259 | size_t *limit) | | 269 | struct glob_limit *limit) |
260 | { | | 270 | { |
261 | int i; | | 271 | int i; |
262 | Char *lm, *ls; | | 272 | Char *lm, *ls; |
263 | const Char *pe, *pm, *pl; | | 273 | const Char *pe, *pm, *pl; |
264 | Char patbuf[MAXPATHLEN + 1]; | | 274 | Char patbuf[MAXPATHLEN + 1]; |
265 | | | 275 | |
266 | _DIAGASSERT(ptr != NULL); | | 276 | _DIAGASSERT(ptr != NULL); |
267 | _DIAGASSERT(pattern != NULL); | | 277 | _DIAGASSERT(pattern != NULL); |
268 | _DIAGASSERT(pglob != NULL); | | 278 | _DIAGASSERT(pglob != NULL); |
269 | _DIAGASSERT(rv != NULL); | | 279 | _DIAGASSERT(rv != NULL); |
270 | | | 280 | |
271 | /* copy part up to the brace */ | | 281 | /* copy part up to the brace */ |
272 | for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) | | 282 | for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) |
| @@ -451,27 +461,27 @@ globtilde(const Char *pattern, Char *pat | | | @@ -451,27 +461,27 @@ globtilde(const Char *pattern, Char *pat |
451 | | | 461 | |
452 | return patbuf; | | 462 | return patbuf; |
453 | } | | 463 | } |
454 | | | 464 | |
455 | | | 465 | |
456 | /* | | 466 | /* |
457 | * The main glob() routine: compiles the pattern (optionally processing | | 467 | * The main glob() routine: compiles the pattern (optionally processing |
458 | * quotes), calls glob1() to do the real pattern matching, and finally | | 468 | * quotes), calls glob1() to do the real pattern matching, and finally |
459 | * sorts the list (unless unsorted operation is requested). Returns 0 | | 469 | * sorts the list (unless unsorted operation is requested). Returns 0 |
460 | * if things went well, nonzero if errors occurred. It is not an error | | 470 | * if things went well, nonzero if errors occurred. It is not an error |
461 | * to find no matches. | | 471 | * to find no matches. |
462 | */ | | 472 | */ |
463 | static int | | 473 | static int |
464 | glob0(const Char *pattern, glob_t *pglob, size_t *limit) | | 474 | glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit) |
465 | { | | 475 | { |
466 | const Char *qpatnext; | | 476 | const Char *qpatnext; |
467 | int c, error; | | 477 | int c, error; |
468 | __gl_size_t oldpathc; | | 478 | __gl_size_t oldpathc; |
469 | Char *bufnext, patbuf[MAXPATHLEN+1]; | | 479 | Char *bufnext, patbuf[MAXPATHLEN+1]; |
470 | | | 480 | |
471 | _DIAGASSERT(pattern != NULL); | | 481 | _DIAGASSERT(pattern != NULL); |
472 | _DIAGASSERT(pglob != NULL); | | 482 | _DIAGASSERT(pglob != NULL); |
473 | | | 483 | |
474 | if ((qpatnext = globtilde(pattern, patbuf, sizeof(patbuf), | | 484 | if ((qpatnext = globtilde(pattern, patbuf, sizeof(patbuf), |
475 | pglob)) == NULL) | | 485 | pglob)) == NULL) |
476 | return GLOB_ABEND; | | 486 | return GLOB_ABEND; |
477 | oldpathc = pglob->gl_pathc; | | 487 | oldpathc = pglob->gl_pathc; |
| @@ -557,77 +567,78 @@ glob0(const Char *pattern, glob_t *pglob | | | @@ -557,77 +567,78 @@ glob0(const Char *pattern, glob_t *pglob |
557 | } | | 567 | } |
558 | | | 568 | |
559 | static int | | 569 | static int |
560 | compare(const void *p, const void *q) | | 570 | compare(const void *p, const void *q) |
561 | { | | 571 | { |
562 | | | 572 | |
563 | _DIAGASSERT(p != NULL); | | 573 | _DIAGASSERT(p != NULL); |
564 | _DIAGASSERT(q != NULL); | | 574 | _DIAGASSERT(q != NULL); |
565 | | | 575 | |
566 | return strcoll(*(const char * const *)p, *(const char * const *)q); | | 576 | return strcoll(*(const char * const *)p, *(const char * const *)q); |
567 | } | | 577 | } |
568 | | | 578 | |
569 | static int | | 579 | static int |
570 | glob1(Char *pattern, glob_t *pglob, size_t *limit) | | 580 | glob1(Char *pattern, glob_t *pglob, struct glob_limit *limit) |
571 | { | | 581 | { |
572 | Char pathbuf[MAXPATHLEN+1]; | | 582 | Char pathbuf[MAXPATHLEN+1]; |
573 | | | 583 | |
574 | _DIAGASSERT(pattern != NULL); | | 584 | _DIAGASSERT(pattern != NULL); |
575 | _DIAGASSERT(pglob != NULL); | | 585 | _DIAGASSERT(pglob != NULL); |
576 | | | 586 | |
577 | /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ | | 587 | /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ |
578 | if (*pattern == EOS) | | 588 | if (*pattern == EOS) |
579 | return 0; | | 589 | return 0; |
580 | /* | | 590 | /* |
581 | * we save one character so that we can use ptr >= limit, | | 591 | * we save one character so that we can use ptr >= limit, |
582 | * in the general case when we are appending non nul chars only. | | 592 | * in the general case when we are appending non nul chars only. |
583 | */ | | 593 | */ |
584 | return glob2(pathbuf, pathbuf, | | 594 | return glob2(pathbuf, pathbuf, |
585 | pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern, | | 595 | pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern, |
586 | pglob, limit); | | 596 | pglob, limit); |
587 | } | | 597 | } |
588 | | | 598 | |
589 | /* | | 599 | /* |
590 | * The functions glob2 and glob3 are mutually recursive; there is one level | | 600 | * The functions glob2 and glob3 are mutually recursive; there is one level |
591 | * of recursion for each segment in the pattern that contains one or more | | 601 | * of recursion for each segment in the pattern that contains one or more |
592 | * meta characters. | | 602 | * meta characters. |
593 | */ | | 603 | */ |
594 | static int | | 604 | static int |
595 | glob2(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, glob_t *pglob, | | 605 | glob2(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern, |
596 | size_t *limit) | | 606 | glob_t *pglob, struct glob_limit *limit) |
597 | { | | 607 | { |
598 | __gl_stat_t sb; | | 608 | __gl_stat_t sb; |
599 | Char *p, *q; | | 609 | const Char *p; |
| | | 610 | Char *q; |
600 | int anymeta; | | 611 | int anymeta; |
601 | Char *pend; | | 612 | Char *pend; |
602 | ptrdiff_t diff; | | 613 | ptrdiff_t diff; |
603 | | | 614 | |
604 | _DIAGASSERT(pathbuf != NULL); | | 615 | _DIAGASSERT(pathbuf != NULL); |
605 | _DIAGASSERT(pathend != NULL); | | 616 | _DIAGASSERT(pathend != NULL); |
606 | _DIAGASSERT(pattern != NULL); | | 617 | _DIAGASSERT(pattern != NULL); |
607 | _DIAGASSERT(pglob != NULL); | | 618 | _DIAGASSERT(pglob != NULL); |
608 | | | 619 | |
609 | /* | | 620 | /* |
610 | * Loop over pattern segments until end of pattern or until | | 621 | * Loop over pattern segments until end of pattern or until |
611 | * segment with meta character found. | | 622 | * segment with meta character found. |
612 | */ | | 623 | */ |
613 | for (anymeta = 0;;) { | | 624 | for (anymeta = 0;;) { |
614 | if (*pattern == EOS) { /* End of pattern? */ | | 625 | if (*pattern == EOS) { /* End of pattern? */ |
615 | *pathend = EOS; | | 626 | *pathend = EOS; |
616 | if (g_lstat(pathbuf, &sb, pglob)) | | 627 | if (g_lstat(pathbuf, &sb, pglob)) |
617 | return 0; | | 628 | return 0; |
618 | | | 629 | |
619 | if ((pglob->gl_flags & GLOB_LIMIT) && | | 630 | if ((pglob->gl_flags & GLOB_LIMIT) && |
620 | limit[GLOB_INDEX_STAT]++ >= GLOB_LIMIT_STAT) { | | 631 | limit->l_stat++ >= GLOB_LIMIT_STAT) { |
621 | errno = 0; | | 632 | errno = 0; |
622 | *pathend++ = SEP; | | 633 | *pathend++ = SEP; |
623 | *pathend = EOS; | | 634 | *pathend = EOS; |
624 | return GLOB_NOSPACE; | | 635 | return GLOB_NOSPACE; |
625 | } | | 636 | } |
626 | if (((pglob->gl_flags & GLOB_MARK) && | | 637 | if (((pglob->gl_flags & GLOB_MARK) && |
627 | pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || | | 638 | pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || |
628 | (S_ISLNK(sb.st_mode) && | | 639 | (S_ISLNK(sb.st_mode) && |
629 | (g_stat(pathbuf, &sb, pglob) == 0) && | | 640 | (g_stat(pathbuf, &sb, pglob) == 0) && |
630 | S_ISDIR(sb.st_mode)))) { | | 641 | S_ISDIR(sb.st_mode)))) { |
631 | if (pathend >= pathlim) | | 642 | if (pathend >= pathlim) |
632 | return GLOB_ABORTED; | | 643 | return GLOB_ABORTED; |
633 | *pathend++ = SEP; | | 644 | *pathend++ = SEP; |
| @@ -673,28 +684,28 @@ glob2(Char *pathbuf, Char *pathend, Char | | | @@ -673,28 +684,28 @@ glob2(Char *pathbuf, Char *pathend, Char |
673 | while (*pattern == SEP) { | | 684 | while (*pattern == SEP) { |
674 | if (pathend >= pathlim) | | 685 | if (pathend >= pathlim) |
675 | return GLOB_ABORTED; | | 686 | return GLOB_ABORTED; |
676 | *pathend++ = *pattern++; | | 687 | *pathend++ = *pattern++; |
677 | } | | 688 | } |
678 | } else /* Need expansion, recurse. */ | | 689 | } else /* Need expansion, recurse. */ |
679 | return glob3(pathbuf, pathend, pathlim, pattern, p, | | 690 | return glob3(pathbuf, pathend, pathlim, pattern, p, |
680 | pglob, limit); | | 691 | pglob, limit); |
681 | } | | 692 | } |
682 | /* NOTREACHED */ | | 693 | /* NOTREACHED */ |
683 | } | | 694 | } |
684 | | | 695 | |
685 | static int | | 696 | static int |
686 | glob3(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, | | 697 | glob3(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern, |
687 | Char *restpattern, glob_t *pglob, size_t *limit) | | 698 | const Char *restpattern, glob_t *pglob, struct glob_limit *limit) |
688 | { | | 699 | { |
689 | struct dirent *dp; | | 700 | struct dirent *dp; |
690 | DIR *dirp; | | 701 | DIR *dirp; |
691 | int error; | | 702 | int error; |
692 | char buf[MAXPATHLEN]; | | 703 | char buf[MAXPATHLEN]; |
693 | | | 704 | |
694 | /* | | 705 | /* |
695 | * The readdirfunc declaration can't be prototyped, because it is | | 706 | * The readdirfunc declaration can't be prototyped, because it is |
696 | * assigned, below, to two functions which are prototyped in glob.h | | 707 | * assigned, below, to two functions which are prototyped in glob.h |
697 | * and dirent.h as taking pointers to differently typed opaque | | 708 | * and dirent.h as taking pointers to differently typed opaque |
698 | * structures. | | 709 | * structures. |
699 | */ | | 710 | */ |
700 | struct dirent *(*readdirfunc)(void *); | | 711 | struct dirent *(*readdirfunc)(void *); |
| @@ -730,27 +741,27 @@ glob3(Char *pathbuf, Char *pathend, Char | | | @@ -730,27 +741,27 @@ glob3(Char *pathbuf, Char *pathend, Char |
730 | | | 741 | |
731 | error = 0; | | 742 | error = 0; |
732 | | | 743 | |
733 | /* Search directory for matching names. */ | | 744 | /* Search directory for matching names. */ |
734 | if (pglob->gl_flags & GLOB_ALTDIRFUNC) | | 745 | if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
735 | readdirfunc = pglob->gl_readdir; | | 746 | readdirfunc = pglob->gl_readdir; |
736 | else | | 747 | else |
737 | readdirfunc = (struct dirent *(*)__P((void *))) readdir; | | 748 | readdirfunc = (struct dirent *(*)__P((void *))) readdir; |
738 | while ((dp = (*readdirfunc)(dirp)) != NULL) { | | 749 | while ((dp = (*readdirfunc)(dirp)) != NULL) { |
739 | u_char *sc; | | 750 | u_char *sc; |
740 | Char *dc; | | 751 | Char *dc; |
741 | | | 752 | |
742 | if ((pglob->gl_flags & GLOB_LIMIT) && | | 753 | if ((pglob->gl_flags & GLOB_LIMIT) && |
743 | limit[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) { | | 754 | limit->l_readdir++ >= GLOB_LIMIT_READDIR) { |
744 | errno = 0; | | 755 | errno = 0; |
745 | *pathend++ = SEP; | | 756 | *pathend++ = SEP; |
746 | *pathend = EOS; | | 757 | *pathend = EOS; |
747 | return GLOB_NOSPACE; | | 758 | return GLOB_NOSPACE; |
748 | } | | 759 | } |
749 | | | 760 | |
750 | /* | | 761 | /* |
751 | * Initial DOT must be matched literally, unless we have | | 762 | * Initial DOT must be matched literally, unless we have |
752 | * GLOB_PERIOD set. | | 763 | * GLOB_PERIOD set. |
753 | */ | | 764 | */ |
754 | if ((pglob->gl_flags & GLOB_PERIOD) == 0) | | 765 | if ((pglob->gl_flags & GLOB_PERIOD) == 0) |
755 | if (dp->d_name[0] == DOT && *pattern != DOT) | | 766 | if (dp->d_name[0] == DOT && *pattern != DOT) |
756 | continue; | | 767 | continue; |
| @@ -819,79 +830,83 @@ glob3(Char *pathbuf, Char *pathend, Char | | | @@ -819,79 +830,83 @@ glob3(Char *pathbuf, Char *pathend, Char |
819 | * add the new item, and update gl_pathc. | | 830 | * add the new item, and update gl_pathc. |
820 | * | | 831 | * |
821 | * This assumes the BSD realloc, which only copies the block when its size | | 832 | * This assumes the BSD realloc, which only copies the block when its size |
822 | * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic | | 833 | * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic |
823 | * behavior. | | 834 | * behavior. |
824 | * | | 835 | * |
825 | * Return 0 if new item added, error code if memory couldn't be allocated. | | 836 | * Return 0 if new item added, error code if memory couldn't be allocated. |
826 | * | | 837 | * |
827 | * Invariant of the glob_t structure: | | 838 | * Invariant of the glob_t structure: |
828 | * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and | | 839 | * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and |
829 | * gl_pathv points to (gl_offs + gl_pathc + 1) items. | | 840 | * gl_pathv points to (gl_offs + gl_pathc + 1) items. |
830 | */ | | 841 | */ |
831 | static int | | 842 | static int |
832 | globextend(const Char *path, glob_t *pglob, size_t *limit) | | 843 | globextend(const Char *path, glob_t *pglob, struct glob_limit *limit) |
833 | { | | 844 | { |
834 | char **pathv; | | 845 | char **pathv; |
835 | size_t i, newsize, len; | | 846 | size_t i, newsize, len; |
836 | char *copy; | | 847 | char *copy; |
837 | const Char *p; | | 848 | const Char *p; |
838 | | | 849 | |
839 | _DIAGASSERT(path != NULL); | | 850 | _DIAGASSERT(path != NULL); |
840 | _DIAGASSERT(pglob != NULL); | | 851 | _DIAGASSERT(pglob != NULL); |
841 | | | 852 | |
842 | newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); | | 853 | newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); |
| | | 854 | if ((pglob->gl_flags & GLOB_LIMIT) && |
| | | 855 | newsize > GLOB_LIMIT_PATH * sizeof(*pathv)) |
| | | 856 | goto nospace; |
843 | pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) : | | 857 | pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) : |
844 | malloc(newsize); | | 858 | malloc(newsize); |
845 | if (pathv == NULL) | | 859 | if (pathv == NULL) |
846 | return GLOB_NOSPACE; | | 860 | return GLOB_NOSPACE; |
847 | | | 861 | |
848 | if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { | | 862 | if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { |
849 | /* first time around -- clear initial gl_offs items */ | | 863 | /* first time around -- clear initial gl_offs items */ |
850 | pathv += pglob->gl_offs; | | 864 | pathv += pglob->gl_offs; |
851 | for (i = pglob->gl_offs + 1; --i > 0; ) | | 865 | for (i = pglob->gl_offs + 1; --i > 0; ) |
852 | *--pathv = NULL; | | 866 | *--pathv = NULL; |
853 | } | | 867 | } |
854 | pglob->gl_pathv = pathv; | | 868 | pglob->gl_pathv = pathv; |
855 | | | 869 | |
856 | for (p = path; *p++;) | | 870 | for (p = path; *p++;) |
857 | continue; | | 871 | continue; |
858 | len = (size_t)(p - path); | | 872 | len = (size_t)(p - path); |
859 | limit[GLOB_INDEX_MALLOC] += len; | | 873 | limit->l_string += len; |
860 | if ((copy = malloc(len)) != NULL) { | | 874 | if ((copy = malloc(len)) != NULL) { |
861 | if (g_Ctoc(path, copy, len)) { | | 875 | if (g_Ctoc(path, copy, len)) { |
862 | free(copy); | | 876 | free(copy); |
863 | return GLOB_ABORTED; | | 877 | return GLOB_ABORTED; |
864 | } | | 878 | } |
865 | pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; | | 879 | pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; |
866 | } | | 880 | } |
867 | pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; | | 881 | pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; |
868 | | | 882 | |
869 | if ((pglob->gl_flags & GLOB_LIMIT) && | | 883 | if ((pglob->gl_flags & GLOB_LIMIT) && |
870 | (newsize + limit[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) { | | 884 | (newsize + limit->l_string) >= GLOB_LIMIT_STRING) |
871 | errno = 0; | | 885 | goto nospace; |
872 | return GLOB_NOSPACE; | | | |
873 | } | | | |
874 | | | 886 | |
875 | return copy == NULL ? GLOB_NOSPACE : 0; | | 887 | return copy == NULL ? GLOB_NOSPACE : 0; |
| | | 888 | nospace: |
| | | 889 | errno = 0; |
| | | 890 | return GLOB_NOSPACE; |
876 | } | | 891 | } |
877 | | | 892 | |
878 | | | 893 | |
879 | /* | | 894 | /* |
880 | * pattern matching function for filenames. Each occurrence of the * | | 895 | * pattern matching function for filenames. Each occurrence of the * |
881 | * pattern causes a recursion level. | | 896 | * pattern causes a recursion level. |
882 | */ | | 897 | */ |
883 | static int | | 898 | static int |
884 | match(Char *name, Char *pat, Char *patend) | | 899 | match(const Char *name, const Char *pat, const Char *patend) |
885 | { | | 900 | { |
886 | int ok, negate_range; | | 901 | int ok, negate_range; |
887 | Char c, k; | | 902 | Char c, k; |
888 | | | 903 | |
889 | _DIAGASSERT(name != NULL); | | 904 | _DIAGASSERT(name != NULL); |
890 | _DIAGASSERT(pat != NULL); | | 905 | _DIAGASSERT(pat != NULL); |
891 | _DIAGASSERT(patend != NULL); | | 906 | _DIAGASSERT(patend != NULL); |
892 | | | 907 | |
893 | while (pat < patend) { | | 908 | while (pat < patend) { |
894 | c = *pat++; | | 909 | c = *pat++; |
895 | switch (c & M_MASK) { | | 910 | switch (c & M_MASK) { |
896 | case M_ALL: | | 911 | case M_ALL: |
897 | if (pat == patend) | | 912 | if (pat == patend) |