summaryrefslogtreecommitdiff
path: root/net/tnftp/files/libnetbsd/glob.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tnftp/files/libnetbsd/glob.c')
-rw-r--r--net/tnftp/files/libnetbsd/glob.c456
1 files changed, 356 insertions, 100 deletions
diff --git a/net/tnftp/files/libnetbsd/glob.c b/net/tnftp/files/libnetbsd/glob.c
index a3df04233c3..c9ba9a87d30 100644
--- a/net/tnftp/files/libnetbsd/glob.c
+++ b/net/tnftp/files/libnetbsd/glob.c
@@ -1,5 +1,5 @@
-/* $NetBSD: glob.c,v 1.5 2009/02/19 00:51:12 abs Exp $ */
-/* from NetBSD: glob.c,v 1.16 2006/03/26 18:11:22 christos Exp */
+/* $NetBSD: glob.c,v 1.6 2014/10/31 18:59:32 spz Exp $ */
+/* from: NetBSD: glob.c,v 1.34 2013/02/21 18:17:43 christos Exp */
/*
* Copyright (c) 1989, 1993
@@ -51,19 +51,58 @@
* expand ~user/foo to the /home/dir/of/user/foo
* GLOB_BRACE:
* expand {1,2}{a,b} to 1a 1b 2a 2b
+ * GLOB_PERIOD:
+ * allow metacharacters to match leading dots in filenames.
+ * GLOB_NO_DOTDIRS:
+ * . and .. are hidden from wildcards, even if GLOB_PERIOD is set.
* gl_matchc:
* Number of matches in the current invocation of glob.
*/
#include "tnftp.h"
-/* At least Ubuntu 8.10 jumps through hoops to *undefine* ARG_MAX */
-#if !defined(ARG_MAX)
-# define ARG_MAX sysconf(_SC_ARG_MAX)
+#if 0
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
#endif
+#define NO_GETPW_R
+
+#define GLOB_LIMIT_STRING 65536 /* 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_PATH 1024 /* number of path elements */
+#define GLOB_LIMIT_BRACE 128 /* Number of brace calls */
+
+struct glob_limit {
+ size_t l_string;
+ size_t l_stat;
+ size_t l_readdir;
+ size_t l_brace;
+};
+
#undef TILDE /* XXX: AIX 4.1.5 has this in <sys/ioctl.h> */
+/*
+ * XXX: For NetBSD 1.4.x compatibility. (kill me l8r)
+ */
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(a)
+#endif
+
#define DOLLAR '$'
#define DOT '.'
#define EOS '\0'
@@ -116,31 +155,36 @@ typedef char Char;
static int compare(const void *, const void *);
static int g_Ctoc(const Char *, char *, size_t);
-static int g_lstat(Char *, __gl_stat_t *, glob_t *);
+static int g_lstat(Char *, __gl_stat_t *, glob_t *);
static DIR *g_opendir(Char *, glob_t *);
static Char *g_strchr(const Char *, int);
static int g_stat(Char *, __gl_stat_t *, glob_t *);
-static int glob0(const Char *, glob_t *);
-static int glob1(Char *, glob_t *, size_t *);
-static int glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *);
-static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *,
- size_t *);
-static int globextend(const Char *, glob_t *, size_t *);
+static int glob0(const Char *, glob_t *, struct glob_limit *);
+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 *,
+ 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 *);
-static int globexp2(const Char *, const Char *, glob_t *, int *);
-static int match(Char *, Char *, Char *);
+static int globexp1(const Char *, glob_t *, struct glob_limit *);
+static int globexp2(const Char *, const Char *, glob_t *, int *,
+ struct glob_limit *);
+static int match(const Char *, const Char *, const Char *);
#ifdef DEBUG
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 * pattern, int flags, int (*errfunc)(const char *,
+ int), glob_t * pglob)
{
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 unsigned char *) pattern;
if (!(flags & GLOB_APPEND)) {
@@ -174,9 +218,9 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
*bufnext = EOS;
if (flags & GLOB_BRACE)
- return globexp1(patbuf, pglob);
+ return globexp1(patbuf, pglob, &limit);
else
- return glob0(patbuf, pglob);
+ return glob0(patbuf, pglob, &limit);
}
/*
@@ -185,20 +229,29 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
* characters
*/
static int
-globexp1(const Char *pattern, glob_t *pglob)
+globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
{
const Char* ptr = pattern;
int rv;
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_brace++ >= GLOB_LIMIT_BRACE) {
+ errno = 0;
+ return GLOB_NOSPACE;
+ }
+
/* Protect a single {}, for find(1), like csh */
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
- return glob0(pattern, pglob);
+ return glob0(pattern, pglob, limit);
while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
- if (!globexp2(ptr, pattern, pglob, &rv))
+ if (!globexp2(ptr, pattern, pglob, &rv, limit))
return rv;
- return glob0(pattern, pglob);
+ return glob0(pattern, pglob, limit);
}
@@ -208,13 +261,19 @@ globexp1(const Char *pattern, glob_t *pglob)
* If it fails then it tries to glob the rest of the pattern and returns.
*/
static int
-globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv)
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
+ struct glob_limit *limit)
{
int i;
Char *lm, *ls;
const Char *pe, *pm, *pl;
Char patbuf[MAXPATHLEN + 1];
+ _DIAGASSERT(ptr != NULL);
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+ _DIAGASSERT(rv != NULL);
+
/* copy part up to the brace */
for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
continue;
@@ -248,7 +307,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv)
* we use `pattern', not `patbuf' here so that that
* unbalanced braces are passed to the match
*/
- *rv = glob0(pattern, pglob);
+ *rv = glob0(pattern, pglob, limit);
return 0;
}
@@ -293,9 +352,9 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv)
/* Expand the current pattern */
#ifdef DEBUG
- qprintf("globexp2:", patbuf);
+ qprintf("globexp2", patbuf);
#endif
- *rv = globexp1(patbuf, pglob);
+ *rv = globexp1(patbuf, pglob, limit);
/* move after the comma, to the next string */
pl = pm + 1;
@@ -324,9 +383,17 @@ globtilde(const Char *pattern, Char *patbuf, size_t patsize, glob_t *pglob)
Char *b;
char *d;
Char *pend = &patbuf[patsize / sizeof(Char)];
+#ifndef NO_GETPW_R
+ struct passwd pwres;
+ char pwbuf[1024];
+#endif
pend--;
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(patbuf != NULL);
+ _DIAGASSERT(pglob != NULL);
+
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
return pattern;
@@ -348,7 +415,12 @@ globtilde(const Char *pattern, Char *patbuf, size_t patsize, glob_t *pglob)
* first and then trying the password file
*/
if ((h = getenv("HOME")) == NULL) {
+#ifdef NO_GETPW_R
if ((pwd = getpwuid(getuid())) == NULL)
+#else
+ if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf),
+ &pwd) != 0 || pwd == NULL)
+#endif
return pattern;
else
h = pwd->pw_dir;
@@ -358,7 +430,12 @@ globtilde(const Char *pattern, Char *patbuf, size_t patsize, glob_t *pglob)
/*
* Expand a ~user
*/
+#ifdef NO_GETPW_R
if ((pwd = getpwnam(d)) == NULL)
+#else
+ if (getpwnam_r(d, &pwres, pwbuf, sizeof(pwbuf), &pwd) != 0 ||
+ pwd == NULL)
+#endif
return pattern;
else
h = pwd->pw_dir;
@@ -390,13 +467,15 @@ globtilde(const Char *pattern, Char *patbuf, size_t patsize, glob_t *pglob)
* to find no matches.
*/
static int
-glob0(const Char *pattern, glob_t *pglob)
+glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
{
const Char *qpatnext;
int c, error;
__gl_size_t oldpathc;
Char *bufnext, patbuf[MAXPATHLEN+1];
- size_t limit = 0;
+
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(pglob != NULL);
if ((qpatnext = globtilde(pattern, patbuf, sizeof(patbuf),
pglob)) == NULL)
@@ -440,10 +519,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:
@@ -453,11 +535,11 @@ 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)
- return(error);
+ if ((error = glob1(patbuf, pglob, limit)) != 0)
+ return error;
if (pglob->gl_pathc == oldpathc) {
/*
@@ -470,9 +552,9 @@ glob0(const Char *pattern, glob_t *pglob)
if ((pglob->gl_flags & GLOB_NOCHECK) ||
((pglob->gl_flags & (GLOB_NOMAGIC|GLOB_MAGCHAR))
== GLOB_NOMAGIC)) {
- return globextend(pattern, pglob, &limit);
+ return globextend(pattern, pglob, limit);
} else {
- return (GLOB_NOMATCH);
+ return GLOB_NOMATCH;
}
} else if (!(pglob->gl_flags & GLOB_NOSORT)) {
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
@@ -480,32 +562,37 @@ glob0(const Char *pattern, glob_t *pglob)
compare);
}
- return(0);
+ return 0;
}
static int
compare(const void *p, const void *q)
{
- return(strcoll(*(const char * const *)p, *(const char * const *)q));
+ _DIAGASSERT(p != NULL);
+ _DIAGASSERT(q != NULL);
+
+ return strcoll(*(const char * const *)p, *(const char * const *)q);
}
static int
-glob1(Char *pattern, glob_t *pglob, size_t *limit)
+glob1(Char *pattern, glob_t *pglob, struct glob_limit *limit)
{
Char pathbuf[MAXPATHLEN+1];
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
if (*pattern == EOS)
- return(0);
+ return 0;
/*
* we save one character so that we can use ptr >= limit,
* in the general case when we are appending non nul chars only.
*/
- return(glob2(pathbuf, pathbuf,
- pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1,
- pattern,
- pglob, limit));
+ return glob2(pathbuf, pathbuf,
+ pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern,
+ pglob, limit);
}
/*
@@ -514,13 +601,22 @@ glob1(Char *pattern, glob_t *pglob, size_t *limit)
* 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, struct glob_limit *limit)
{
__gl_stat_t sb;
- Char *p, *q;
+ const Char *p;
+ Char *q;
int anymeta;
+ _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.
@@ -529,20 +625,27 @@ glob2(Char *pathbuf, Char *pathend, Char *pathlim,
if (*pattern == EOS) { /* End of pattern? */
*pathend = EOS;
if (g_lstat(pathbuf, &sb, pglob))
- return(0);
+ return 0;
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_stat++ >= GLOB_LIMIT_STAT) {
+ errno = 0;
+ *pathend++ = SEP;
+ *pathend = EOS;
+ return GLOB_NOSPACE;
+ }
if (((pglob->gl_flags & GLOB_MARK) &&
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
(S_ISLNK(sb.st_mode) &&
(g_stat(pathbuf, &sb, pglob) == 0) &&
S_ISDIR(sb.st_mode)))) {
if (pathend >= pathlim)
- return (GLOB_ABORTED);
+ return GLOB_ABORTED;
*pathend++ = SEP;
*pathend = EOS;
}
++pglob->gl_matchc;
- return(globextend(pathbuf, pglob, limit));
+ return globextend(pathbuf, pglob, limit);
}
/* Find end of next segment, copy tentatively to pathend. */
@@ -556,7 +659,7 @@ glob2(Char *pathbuf, Char *pathend, Char *pathlim,
*q++ = *p++;
}
- if (!anymeta) { /* No expansion, do next segment. */
+ if (!anymeta) {
pathend = q;
pattern = p;
while (*pattern == SEP) {
@@ -565,20 +668,25 @@ glob2(Char *pathbuf, Char *pathend, Char *pathlim,
*pathend++ = *pattern++;
}
} else /* Need expansion, recurse. */
- return(glob3(pathbuf, pathend, pathlim, pattern, p,
- pglob, limit));
+ return glob3(pathbuf, pathend, pathlim, pattern, p,
+ 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,
+ 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
@@ -588,16 +696,55 @@ glob3(Char *pathbuf, Char *pathend, Char *pathlim,
*/
struct dirent *(*readdirfunc)(void *);
+ _DIAGASSERT(pathbuf != NULL);
+ _DIAGASSERT(pathend != NULL);
+ _DIAGASSERT(pattern != NULL);
+ _DIAGASSERT(restpattern != NULL);
+ _DIAGASSERT(pglob != NULL);
+
*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)))
- return (GLOB_ABORTED);
+ return GLOB_ABORTED;
if (pglob->gl_errfunc(buf, errno) ||
pglob->gl_flags & GLOB_ERR)
- return (GLOB_ABORTED);
+ return GLOB_ABORTED;
}
/*
* Posix/XOpen: glob should return when it encounters a
@@ -606,9 +753,9 @@ glob3(Char *pathbuf, Char *pathend, Char *pathlim,
* I think that Posix had in mind EPERM...
*/
if (pglob->gl_flags & GLOB_ERR)
- return (GLOB_ABORTED);
+ return GLOB_ABORTED;
- return(0);
+ return 0;
}
error = 0;
@@ -622,8 +769,29 @@ glob3(Char *pathbuf, Char *pathend, Char *pathlim,
unsigned char *sc;
Char *dc;
- /* Initial DOT must be matched literally. */
- if (dp->d_name[0] == DOT && *pattern != DOT)
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_readdir++ >= GLOB_LIMIT_READDIR) {
+ errno = 0;
+ *pathend++ = SEP;
+ *pathend = EOS;
+ error = GLOB_NOSPACE;
+ break;
+ }
+
+ /*
+ * Initial DOT must be matched literally, unless we have
+ * GLOB_PERIOD set.
+ */
+ if ((pglob->gl_flags & GLOB_PERIOD) == 0)
+ if (dp->d_name[0] == DOT && *pattern != DOT)
+ continue;
+ /*
+ * If GLOB_NO_DOTDIRS is set, . and .. vanish.
+ */
+ if ((pglob->gl_flags & GLOB_NO_DOTDIRS) &&
+ (dp->d_name[0] == DOT) &&
+ ((dp->d_name[1] == EOS) ||
+ ((dp->d_name[1] == DOT) && (dp->d_name[2] == EOS))))
continue;
/*
* The resulting string contains EOS, so we can
@@ -652,15 +820,36 @@ glob3(Char *pathbuf, Char *pathend, Char *pathlim,
}
}
- 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
@@ -670,14 +859,14 @@ glob3(Char *pathbuf, Char *pathend, Char *pathlim,
* Again Posix X/Open issue with regards to error handling.
*/
if ((error || errno) && (pglob->gl_flags & GLOB_ERR))
- return (GLOB_ABORTED);
+ return GLOB_ABORTED;
- return(error);
+ return error;
}
/*
- * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
+ * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
* add the new item, and update gl_pathc.
*
* This assumes the BSD realloc, which only copies the block when its size
@@ -691,18 +880,24 @@ glob3(Char *pathbuf, Char *pathend, Char *pathlim,
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
*/
static int
-globextend(const Char *path, glob_t *pglob, size_t *limit)
+globextend(const Char *path, glob_t *pglob, struct glob_limit *limit)
{
char **pathv;
size_t i, newsize, len;
char *copy;
const Char *p;
+ _DIAGASSERT(path != NULL);
+ _DIAGASSERT(pglob != NULL);
+
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ newsize > GLOB_LIMIT_PATH * sizeof(*pathv))
+ goto nospace;
pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) :
malloc(newsize);
if (pathv == NULL)
- return(GLOB_NOSPACE);
+ return GLOB_NOSPACE;
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
/* first time around -- clear initial gl_offs items */
@@ -715,22 +910,24 @@ globextend(const Char *path, glob_t *pglob, size_t *limit)
for (p = path; *p++;)
continue;
len = (size_t)(p - path);
- *limit += len;
+ limit->l_string += len;
if ((copy = malloc(len)) != NULL) {
if (g_Ctoc(path, copy, len)) {
free(copy);
- return(GLOB_ABORTED);
+ return GLOB_ABORTED;
}
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
}
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
- if ((pglob->gl_flags & GLOB_LIMIT) && (newsize + *limit) >= ARG_MAX) {
- errno = 0;
- return(GLOB_NOSPACE);
- }
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ (newsize + limit->l_string) >= GLOB_LIMIT_STRING)
+ goto nospace;
- return(copy == NULL ? GLOB_NOSPACE : 0);
+ return copy == NULL ? GLOB_NOSPACE : 0;
+nospace:
+ errno = 0;
+ return GLOB_NOSPACE;
}
@@ -739,30 +936,35 @@ globextend(const Char *path, glob_t *pglob, size_t *limit)
* 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;
+ _DIAGASSERT(name != NULL);
+ _DIAGASSERT(pat != NULL);
+ _DIAGASSERT(patend != NULL);
+
while (pat < patend) {
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);
+ return 1;
+ for (; !match(name, pat, patend); name++)
+ if (*name == EOS)
+ return 0;
+ return 1;
case M_ONE:
if (*name++ == EOS)
- return(0);
+ return 0;
break;
case M_SET:
ok = 0;
if ((k = *name++) == EOS)
- return(0);
+ return 0;
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++pat;
while (((c = *pat++) & M_MASK) != M_END)
@@ -773,15 +975,15 @@ match(Char *name, Char *pat, Char *patend)
} else if (c == k)
ok = 1;
if (ok == negate_range)
- return(0);
+ return 0;
break;
default:
if (*name++ != c)
- return(0);
+ return 0;
break;
}
}
- return(*name == EOS);
+ return *name == EOS;
}
/* Free allocated data belonging to a glob_t structure. */
@@ -791,6 +993,8 @@ globfree(glob_t *pglob)
size_t i;
char **pp;
+ _DIAGASSERT(pglob != NULL);
+
if (pglob->gl_pathv != NULL) {
pp = pglob->gl_pathv + pglob->gl_offs;
for (i = pglob->gl_pathc; i--; ++pp)
@@ -802,11 +1006,47 @@ 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)
{
char buf[MAXPATHLEN];
+ _DIAGASSERT(str != NULL);
+ _DIAGASSERT(pglob != NULL);
+
if (!*str)
(void)strlcpy(buf, ".", sizeof(buf));
else {
@@ -815,9 +1055,9 @@ g_opendir(Char *str, glob_t *pglob)
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return((*pglob->gl_opendir)(buf));
+ return (*pglob->gl_opendir)(buf);
- return(opendir(buf));
+ return opendir(buf);
}
static int
@@ -825,11 +1065,15 @@ g_lstat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
{
char buf[MAXPATHLEN];
+ _DIAGASSERT(fn != NULL);
+ _DIAGASSERT(sb != NULL);
+ _DIAGASSERT(pglob != NULL);
+
if (g_Ctoc(fn, buf, sizeof(buf)))
return -1;
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return((*pglob->gl_lstat)(buf, sb));
- return(lstat(buf, sb));
+ return (*pglob->gl_lstat)(buf, sb);
+ return lstat(buf, sb);
}
static int
@@ -837,22 +1081,28 @@ g_stat(Char *fn, __gl_stat_t *sb, glob_t *pglob)
{
char buf[MAXPATHLEN];
+ _DIAGASSERT(fn != NULL);
+ _DIAGASSERT(sb != NULL);
+ _DIAGASSERT(pglob != NULL);
+
if (g_Ctoc(fn, buf, sizeof(buf)))
return -1;
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return((*pglob->gl_stat)(buf, sb));
- return(stat(buf, sb));
+ return (*pglob->gl_stat)(buf, sb);
+ return stat(buf, sb);
}
static Char *
g_strchr(const Char *str, int ch)
{
+
+ _DIAGASSERT(str != NULL);
+
do {
if (*str == ch)
- /* LINTED this is libc's definition! */
- return (Char *)str;
+ return __UNCONST(str);
} while (*str++);
- return (NULL);
+ return NULL;
}
static int
@@ -860,6 +1110,9 @@ g_Ctoc(const Char *str, char *buf, size_t len)
{
char *dc;
+ _DIAGASSERT(str != NULL);
+ _DIAGASSERT(buf != NULL);
+
if (len == 0)
return 1;
@@ -875,6 +1128,9 @@ qprintf(const char *str, Char *s)
{
Char *p;
+ _DIAGASSERT(str != NULL);
+ _DIAGASSERT(s != NULL);
+
(void)printf("%s:\n", str);
for (p = s; *p; p++)
(void)printf("%c", CHAR(*p));