Deleted Added
full compact
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) */