Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libc/gen Add GLOB_STAR support from Greg Dionne.
details: https://anonhg.NetBSD.org/src/rev/9425e57cda01
branches: trunk
changeset: 757569:9425e57cda01
user: christos <christos%NetBSD.org@localhost>
date: Mon Sep 06 14:40:24 2010 +0000
description:
Add GLOB_STAR support from Greg Dionne.
diffstat:
lib/libc/gen/glob.3 | 11 +++-
lib/libc/gen/glob.c | 126 +++++++++++++++++++++++++++++++++++++++------------
2 files changed, 105 insertions(+), 32 deletions(-)
diffs (281 lines):
diff -r db8935693999 -r 9425e57cda01 lib/libc/gen/glob.3
--- a/lib/libc/gen/glob.3 Mon Sep 06 14:38:56 2010 +0000
+++ b/lib/libc/gen/glob.3 Mon Sep 06 14:40:24 2010 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: glob.3,v 1.37 2010/07/06 14:59:22 christos Exp $
+.\" $NetBSD: glob.3,v 1.38 2010/09/06 14:40:24 christos Exp $
.\"
.\" Copyright (c) 1989, 1991, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
@@ -31,7 +31,7 @@
.\"
.\" @(#)glob.3 8.3 (Berkeley) 4/16/94
.\"
-.Dd July 6, 2010
+.Dd September 3, 2010
.Dt GLOB 3
.Os
.Sh NAME
@@ -277,6 +277,13 @@
from metacharacter matches, regardless of whether
.Dv GLOB_PERIOD
is set and whether the pattern component begins with a literal period.
+.Dv GLOB_STAR
+Indicates that two adjacent
+.Li *
+characters will do a recursive match in all subdirs, without following
+symbolic links and three adjacent
+.Li *
+characters will also follow symbolic links.
.El
.Pp
If, during the search, a directory is encountered that cannot be opened
diff -r db8935693999 -r 9425e57cda01 lib/libc/gen/glob.c
--- a/lib/libc/gen/glob.c Mon Sep 06 14:38:56 2010 +0000
+++ b/lib/libc/gen/glob.c Mon Sep 06 14:40:24 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: glob.c,v 1.26 2010/07/06 14:59:22 christos Exp $ */
+/* $NetBSD: glob.c,v 1.27 2010/09/06 14:40:25 christos 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.26 2010/07/06 14:59:22 christos Exp $");
+__RCSID("$NetBSD: glob.c,v 1.27 2010/09/06 14:40:25 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -160,16 +160,16 @@
static int g_stat(Char *, __gl_stat_t *, glob_t *);
static int glob0(const Char *, glob_t *, size_t *);
static int glob1(Char *, glob_t *, size_t *);
-static int glob2(Char *, Char *, Char *, Char *, glob_t *,
+static int glob2(Char *, Char *, Char *, const Char *, glob_t *,
size_t *);
-static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *,
- size_t *);
+static int glob3(Char *, Char *, Char *, const Char *, const Char *,
+ const Char *, glob_t *, size_t *);
static int globextend(const Char *, glob_t *, size_t *);
static const Char *globtilde(const Char *, Char *, size_t, glob_t *);
static int globexp1(const Char *, glob_t *, size_t *);
static int globexp2(const Char *, const Char *, glob_t *, int *,
size_t *);
-static int match(Char *, Char *, Char *);
+static int match(const Char *, const Char *, const Char *);
#ifdef DEBUG
static void qprintf(const char *, Char *);
#endif
@@ -346,7 +346,7 @@
/* Expand the current pattern */
#ifdef DEBUG
- qprintf("globexp2:", patbuf);
+ qprintf("globexp2", patbuf);
#endif
*rv = globexp1(patbuf, pglob, limit);
@@ -513,10 +513,13 @@
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:
@@ -526,7 +529,7 @@
}
*bufnext = EOS;
#ifdef DEBUG
- qprintf("glob0:", patbuf);
+ qprintf("glob0", patbuf);
#endif
if ((error = glob1(patbuf, pglob, limit)) != 0)
@@ -592,11 +595,12 @@
* meta characters.
*/
static int
-glob2(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, glob_t *pglob,
- size_t *limit)
+glob2(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
+ glob_t *pglob, size_t *limit)
{
__gl_stat_t sb;
- Char *p, *q;
+ const Char *p;
+ Char *q;
int anymeta;
Char *pend;
ptrdiff_t diff;
@@ -606,6 +610,9 @@
_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.
@@ -677,19 +684,24 @@
}
} 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, Char *pattern,
- Char *restpattern, glob_t *pglob, size_t *limit)
+glob3(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
+ const Char *restpattern, const Char *pglobstar, glob_t *pglob,
+ size_t *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
@@ -708,6 +720,39 @@
*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)))
@@ -789,16 +834,36 @@
}
}
- 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
@@ -881,7 +946,7 @@
* pattern causes a recursion level.
*/
static int
-match(Char *name, Char *pat, Char *patend)
+match(const Char *name, const Char *pat, const Char *patend)
{
int ok, negate_range;
Char c, k;
@@ -894,13 +959,14 @@
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;
@@ -963,7 +1029,7 @@
return 1;
case QUOTE:
- if (quote && pattern[1] != '\0')
+ if (quote && pattern[1] != EOS)
++pattern;
break;
Home |
Main Index |
Thread Index |
Old Index