Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libc/gen/glob.c,v rcsdiff: /ftp/cvs/cvsroot/src/lib/libc/gen/glob.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.23.10.2 retrieving revision 1.35.8.1 diff -u -p -r1.23.10.2 -r1.35.8.1 --- src/lib/libc/gen/glob.c 2011/04/24 15:41:31 1.23.10.2 +++ src/lib/libc/gen/glob.c 2016/09/18 06:10:31 1.35.8.1 @@ -1,4 +1,4 @@ -/* $NetBSD: glob.c,v 1.23.10.2 2011/04/24 15:41:31 riz Exp $ */ +/* $NetBSD: glob.c,v 1.35.8.1 2016/09/18 06:10:31 snj Exp $ */ /* * Copyright (c) 1989, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; #else -__RCSID("$NetBSD: glob.c,v 1.23.10.2 2011/04/24 15:41:31 riz Exp $"); +__RCSID("$NetBSD: glob.c,v 1.35.8.1 2016/09/18 06:10:31 snj Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -87,9 +87,9 @@ __RCSID("$NetBSD: glob.c,v 1.23.10.2 201 #define NO_GETPW_R #endif -#define GLOB_LIMIT_STRING 65536 /* number of readdirs */ +#define GLOB_LIMIT_STRING 524288 /* number of readdirs */ #define GLOB_LIMIT_STAT 128 /* number of stat system calls */ -#define GLOB_LIMIT_READDIR 16384 /* total buffer size of path strings */ +#define GLOB_LIMIT_READDIR 65536 /* total buffer size of path strings */ #define GLOB_LIMIT_PATH 1024 /* number of path elements */ #define GLOB_LIMIT_BRACE 128 /* Number of brace calls */ @@ -132,7 +132,7 @@ struct glob_limit { #define M_MASK 0xffff #define M_ASCII 0x00ff -typedef u_short Char; +typedef unsigned short Char; #else @@ -167,8 +167,8 @@ static int glob0(const Char *, glob_t * static int glob1(Char *, glob_t *, struct glob_limit *); static int glob2(Char *, Char *, Char *, const Char *, glob_t *, struct glob_limit *); -static int glob3(Char *, Char *, Char *, const Char *, const Char *, - glob_t *, struct glob_limit *); +static int glob3(Char *, Char *, Char *, const Char *, const Char *, + const Char *, glob_t *, struct glob_limit *); static int globextend(const Char *, glob_t *, struct glob_limit *); static const Char *globtilde(const Char *, Char *, size_t, glob_t *); static int globexp1(const Char *, glob_t *, struct glob_limit *); @@ -180,17 +180,17 @@ static void qprintf(const char *, Char #endif int -glob(const char *pattern, int flags, int (*errfunc)(const char *, int), - glob_t *pglob) +glob(const char * __restrict pattern, int flags, int (*errfunc)(const char *, + int), glob_t * __restrict pglob) { - const u_char *patnext; + const unsigned char *patnext; int c; Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; struct glob_limit limit = { 0, 0, 0, 0 }; _DIAGASSERT(pattern != NULL); - patnext = (const u_char *) pattern; + patnext = (const unsigned char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; @@ -356,7 +356,7 @@ globexp2(const Char *ptr, const Char *pa /* Expand the current pattern */ #ifdef DEBUG - qprintf("globexp2:", patbuf); + qprintf("globexp2", patbuf); #endif *rv = globexp1(patbuf, pglob, limit); @@ -523,10 +523,13 @@ glob0(const Char *pattern, glob_t *pglob break; case STAR: pglob->gl_flags |= GLOB_MAGCHAR; - /* collapse adjacent stars to one, + /* collapse adjacent stars to one [or three if globstar] * to avoid exponential behavior */ - if (bufnext == patbuf || bufnext[-1] != M_ALL) + if (bufnext == patbuf || bufnext[-1] != M_ALL || + ((pglob->gl_flags & GLOB_STAR) != 0 && + (bufnext - 1 == patbuf || bufnext[-2] != M_ALL || + bufnext - 2 == patbuf || bufnext[-3] != M_ALL))) *bufnext++ = M_ALL; break; default: @@ -536,7 +539,7 @@ glob0(const Char *pattern, glob_t *pglob } *bufnext = EOS; #ifdef DEBUG - qprintf("glob0:", patbuf); + qprintf("glob0", patbuf); #endif if ((error = glob1(patbuf, pglob, limit)) != 0) @@ -609,14 +612,15 @@ glob2(Char *pathbuf, Char *pathend, Char const Char *p; Char *q; int anymeta; - Char *pend; - ptrdiff_t diff; _DIAGASSERT(pathbuf != NULL); _DIAGASSERT(pathend != NULL); _DIAGASSERT(pattern != NULL); _DIAGASSERT(pglob != NULL); +#ifdef DEBUG + qprintf("glob2", pathbuf); +#endif /* * Loop over pattern segments until end of pattern or until * segment with meta character found. @@ -659,26 +663,7 @@ glob2(Char *pathbuf, Char *pathend, Char *q++ = *p++; } - /* - * No expansion, or path ends in slash-dot shash-dot-dot, - * do next segment. - */ - if (pglob->gl_flags & GLOB_PERIOD) { - for (pend = pathend; pend > pathbuf && pend[-1] == '/'; - pend--) - continue; - diff = pend - pathbuf; - } else { - /* XXX: GCC */ - diff = 0; - pend = pathend; - } - - if ((!anymeta) || - ((pglob->gl_flags & GLOB_PERIOD) && - (diff >= 1 && pend[-1] == DOT) && - (diff >= 2 && (pend[-2] == SLASH || pend[-2] == DOT)) && - (diff < 3 || pend[-3] == SLASH))) { + if (!anymeta) { pathend = q; pattern = p; while (*pattern == SEP) { @@ -688,19 +673,24 @@ glob2(Char *pathbuf, Char *pathend, Char } } else /* Need expansion, recurse. */ return glob3(pathbuf, pathend, pathlim, pattern, p, - pglob, limit); + pattern, pglob, limit); } /* NOTREACHED */ } static int glob3(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern, - const Char *restpattern, glob_t *pglob, struct glob_limit *limit) + const Char *restpattern, const Char *pglobstar, glob_t *pglob, + struct glob_limit *limit) { struct dirent *dp; DIR *dirp; + __gl_stat_t sbuf; int error; char buf[MAXPATHLEN]; + int globstar = 0; + int chase_symlinks = 0; + const Char *termstar = NULL; /* * The readdirfunc declaration can't be prototyped, because it is @@ -719,6 +709,39 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend = EOS; errno = 0; + while (pglobstar < restpattern) { + if ((pglobstar[0] & M_MASK) == M_ALL && + (pglobstar[1] & M_MASK) == M_ALL) { + globstar = 1; + chase_symlinks = (pglobstar[2] & M_MASK) == M_ALL; + termstar = pglobstar + (2 + chase_symlinks); + break; + } + pglobstar++; + } + + if (globstar) { + error = pglobstar == pattern && termstar == restpattern ? + *restpattern == EOS ? + glob2(pathbuf, pathend, pathlim, restpattern - 1, pglob, + limit) : + glob2(pathbuf, pathend, pathlim, restpattern + 1, pglob, + limit) : + glob3(pathbuf, pathend, pathlim, pattern, restpattern, + termstar, pglob, limit); + if (error) + return error; + *pathend = EOS; + } + + if (*pathbuf && (g_lstat(pathbuf, &sbuf, pglob) || + !S_ISDIR(sbuf.st_mode) +#ifdef S_IFLINK + && ((globstar && !chase_symlinks) || !S_ISLNK(sbuf.st_mode)) +#endif + )) + return 0; + if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { if (pglob->gl_errfunc) { if (g_Ctoc(pathbuf, buf, sizeof(buf))) @@ -745,9 +768,9 @@ glob3(Char *pathbuf, Char *pathend, Char if (pglob->gl_flags & GLOB_ALTDIRFUNC) readdirfunc = pglob->gl_readdir; else - readdirfunc = (struct dirent *(*)__P((void *))) readdir; + readdirfunc = (struct dirent *(*)(void *)) readdir; while ((dp = (*readdirfunc)(dirp)) != NULL) { - u_char *sc; + unsigned char *sc; Char *dc; if ((pglob->gl_flags & GLOB_LIMIT) && @@ -755,7 +778,8 @@ glob3(Char *pathbuf, Char *pathend, Char errno = 0; *pathend++ = SEP; *pathend = EOS; - return GLOB_NOSPACE; + error = GLOB_NOSPACE; + break; } /* @@ -777,7 +801,7 @@ glob3(Char *pathbuf, Char *pathend, Char * The resulting string contains EOS, so we can * use the pathlim character, if it is the nul */ - for (sc = (u_char *) dp->d_name, dc = pathend; + for (sc = (unsigned char *) dp->d_name, dc = pathend; dc <= pathlim && (*dc++ = *sc++) != EOS;) continue; @@ -800,16 +824,36 @@ glob3(Char *pathbuf, Char *pathend, Char } } - if (!match(pathend, pattern, restpattern)) { + if (globstar) { +#ifdef S_IFLNK + if (!chase_symlinks && + (g_lstat(pathbuf, &sbuf, pglob) || + S_ISLNK(sbuf.st_mode))) + continue; +#endif + + if (!match(pathend, pattern, termstar)) + continue; + + if (--dc < pathlim - 2) + *dc++ = SEP; + *dc = EOS; + error = glob2(pathbuf, dc, pathlim, pglobstar, + pglob, limit); + if (error) + break; *pathend = EOS; - continue; + } else { + if (!match(pathend, pattern, restpattern)) { + *pathend = EOS; + continue; + } + error = glob2(pathbuf, --dc, pathlim, restpattern, + pglob, limit); + if (error) + break; } - error = glob2(pathbuf, --dc, pathlim, restpattern, pglob, - limit); - if (error) - break; } - if (pglob->gl_flags & GLOB_ALTDIRFUNC) (*pglob->gl_closedir)(dirp); else @@ -909,13 +953,14 @@ match(const Char *name, const Char *pat, c = *pat++; switch (c & M_MASK) { case M_ALL: + while (pat < patend && (*pat & M_MASK) == M_ALL) + pat++; /* eat consecutive '*' */ if (pat == patend) return 1; - do - if (match(name, pat, patend)) - return 1; - while (*name++ != EOS); - return 0; + for (; !match(name, pat, patend); name++) + if (*name == EOS) + return 0; + return 1; case M_ONE: if (*name++ == EOS) return 0; @@ -965,6 +1010,39 @@ globfree(glob_t *pglob) } } +#ifndef __LIBC12_SOURCE__ +int +glob_pattern_p(const char *pattern, int quote) +{ + int range = 0; + + for (; *pattern; pattern++) + switch (*pattern) { + case QUESTION: + case STAR: + return 1; + + case QUOTE: + if (quote && pattern[1] != EOS) + ++pattern; + break; + + case LBRACKET: + range = 1; + break; + + case RBRACKET: + if (range) + return 1; + break; + default: + break; + } + + return 0; +} +#endif + static DIR * g_opendir(Char *str, glob_t *pglob) {