| version 1.17, 2006/11/24 19:46:58 |
version 1.18, 2006/12/01 18:57:29 |
| Line 139 typedef char Char; |
|
| Line 139 typedef char Char; |
|
| #define ismeta(c) (((c)&M_QUOTE) != 0) |
#define ismeta(c) (((c)&M_QUOTE) != 0) |
| |
|
| |
|
| static int compare __P((const void *, const void *)); |
static int compare(const void *, const void *); |
| static int g_Ctoc __P((const Char *, char *, size_t)); |
static int g_Ctoc(const Char *, char *, size_t); |
| static int g_lstat __P((Char *, __gl_stat_t *, glob_t *)); |
static int g_lstat(Char *, __gl_stat_t *, glob_t *); |
| static DIR *g_opendir __P((Char *, glob_t *)); |
static DIR *g_opendir(Char *, glob_t *); |
| static Char *g_strchr __P((const Char *, int)); |
static Char *g_strchr(const Char *, int); |
| static int g_stat __P((Char *, __gl_stat_t *, glob_t *)); |
static int g_stat(Char *, __gl_stat_t *, glob_t *); |
| static int glob0 __P((const Char *, glob_t *)); |
static int glob0(const Char *, glob_t *); |
| static int glob1 __P((Char *, glob_t *, size_t *)); |
static int glob1(Char *, glob_t *, size_t *); |
| static int glob2 __P((Char *, Char *, Char *, Char *, glob_t *, |
static int glob2(Char *, Char *, Char *, Char *, glob_t *, |
| size_t *)); |
size_t *); |
| static int glob3 __P((Char *, Char *, Char *, Char *, Char *, glob_t *, |
static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, |
| size_t *)); |
size_t *); |
| static int globextend __P((const Char *, glob_t *, size_t *)); |
static int globextend(const Char *, glob_t *, size_t *); |
| static const Char *globtilde __P((const Char *, Char *, size_t, glob_t *)); |
static const Char *globtilde(const Char *, Char *, size_t, glob_t *); |
| static int globexp1 __P((const Char *, glob_t *)); |
static int globexp1(const Char *, glob_t *); |
| static int globexp2 __P((const Char *, const Char *, glob_t *, int *)); |
static int globexp2(const Char *, const Char *, glob_t *, int *); |
| static int match __P((Char *, Char *, Char *)); |
static int match(Char *, Char *, Char *); |
| #ifdef DEBUG |
#ifdef DEBUG |
| static void qprintf __P((const char *, Char *)); |
static void qprintf(const char *, Char *); |
| #endif |
#endif |
| |
|
| int |
int |
| glob(pattern, flags, errfunc, pglob) |
glob(const char *pattern, int flags, int (*errfunc)(const char *, int), |
| const char *pattern; |
glob_t *pglob) |
| int flags, (*errfunc) __P((const char *, int)); |
|
| glob_t *pglob; |
|
| { |
{ |
| const u_char *patnext; |
const u_char *patnext; |
| int c; |
int c; |
| Line 215 glob(pattern, flags, errfunc, pglob) |
|
| Line 213 glob(pattern, flags, errfunc, pglob) |
|
| * characters |
* characters |
| */ |
*/ |
| static int |
static int |
| globexp1(pattern, pglob) |
globexp1(const Char *pattern, glob_t *pglob) |
| const Char *pattern; |
|
| glob_t *pglob; |
|
| { |
{ |
| const Char* ptr = pattern; |
const Char* ptr = pattern; |
| int rv; |
int rv; |
| Line 243 globexp1(pattern, pglob) |
|
| Line 239 globexp1(pattern, pglob) |
|
| * If it fails then it tries to glob the rest of the pattern and returns. |
* If it fails then it tries to glob the rest of the pattern and returns. |
| */ |
*/ |
| static int |
static int |
| globexp2(ptr, pattern, pglob, rv) |
globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) |
| const Char *ptr, *pattern; |
|
| glob_t *pglob; |
|
| int *rv; |
|
| { |
{ |
| int i; |
int i; |
| Char *lm, *ls; |
Char *lm, *ls; |
| Line 359 globexp2(ptr, pattern, pglob, rv) |
|
| Line 352 globexp2(ptr, pattern, pglob, rv) |
|
| * expand tilde from the passwd file. |
* expand tilde from the passwd file. |
| */ |
*/ |
| static const Char * |
static const Char * |
| globtilde(pattern, patbuf, patsize, pglob) |
globtilde(const Char *pattern, Char *patbuf, size_t patsize, glob_t *pglob) |
| const Char *pattern; |
|
| Char *patbuf; |
|
| size_t patsize; |
|
| glob_t *pglob; |
|
| { |
{ |
| struct passwd *pwd; |
struct passwd *pwd; |
| const char *h; |
const char *h; |
| Line 455 globtilde(pattern, patbuf, patsize, pglo |
|
| Line 444 globtilde(pattern, patbuf, patsize, pglo |
|
| * to find no matches. |
* to find no matches. |
| */ |
*/ |
| static int |
static int |
| glob0(pattern, pglob) |
glob0(const Char *pattern, glob_t *pglob) |
| const Char *pattern; |
|
| glob_t *pglob; |
|
| { |
{ |
| const Char *qpatnext; |
const Char *qpatnext; |
| int c, error; |
int c, error; |
| Line 527 glob0(pattern, pglob) |
|
| Line 514 glob0(pattern, pglob) |
|
| #endif |
#endif |
| |
|
| if ((error = glob1(patbuf, pglob, &limit)) != 0) |
if ((error = glob1(patbuf, pglob, &limit)) != 0) |
| return(error); |
return error; |
| |
|
| if (pglob->gl_pathc == oldpathc) { |
if (pglob->gl_pathc == oldpathc) { |
| /* |
/* |
| Line 542 glob0(pattern, pglob) |
|
| Line 529 glob0(pattern, pglob) |
|
| == GLOB_NOMAGIC)) { |
== GLOB_NOMAGIC)) { |
| return globextend(pattern, pglob, &limit); |
return globextend(pattern, pglob, &limit); |
| } else { |
} else { |
| return (GLOB_NOMATCH); |
return GLOB_NOMATCH; |
| } |
} |
| } else if (!(pglob->gl_flags & GLOB_NOSORT)) { |
} else if (!(pglob->gl_flags & GLOB_NOSORT)) { |
| qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, |
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, |
| Line 550 glob0(pattern, pglob) |
|
| Line 537 glob0(pattern, pglob) |
|
| compare); |
compare); |
| } |
} |
| |
|
| return(0); |
return 0; |
| } |
} |
| |
|
| static int |
static int |
| compare(p, q) |
compare(const void *p, const void *q) |
| const void *p, *q; |
|
| { |
{ |
| |
|
| _DIAGASSERT(p != NULL); |
_DIAGASSERT(p != NULL); |
| _DIAGASSERT(q != NULL); |
_DIAGASSERT(q != NULL); |
| |
|
| return(strcoll(*(const char * const *)p, *(const char * const *)q)); |
return strcoll(*(const char * const *)p, *(const char * const *)q); |
| } |
} |
| |
|
| static int |
static int |
| glob1(pattern, pglob, limit) |
glob1(Char *pattern, glob_t *pglob, size_t *limit) |
| Char *pattern; |
|
| glob_t *pglob; |
|
| size_t *limit; |
|
| { |
{ |
| Char pathbuf[MAXPATHLEN+1]; |
Char pathbuf[MAXPATHLEN+1]; |
| |
|
| Line 577 glob1(pattern, pglob, limit) |
|
| Line 560 glob1(pattern, pglob, limit) |
|
| |
|
| /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ |
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ |
| if (*pattern == EOS) |
if (*pattern == EOS) |
| return(0); |
return 0; |
| /* |
/* |
| * we save one character so that we can use ptr >= limit, |
* we save one character so that we can use ptr >= limit, |
| * in the general case when we are appending non nul chars only. |
* in the general case when we are appending non nul chars only. |
| */ |
*/ |
| return(glob2(pathbuf, pathbuf, |
return glob2(pathbuf, pathbuf, |
| pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, |
pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern, |
| pattern, |
pglob, limit); |
| pglob, limit)); |
|
| } |
} |
| |
|
| /* |
/* |
| Line 594 glob1(pattern, pglob, limit) |
|
| Line 576 glob1(pattern, pglob, limit) |
|
| * meta characters. |
* meta characters. |
| */ |
*/ |
| static int |
static int |
| glob2(pathbuf, pathend, pathlim, pattern, pglob, limit) |
glob2(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, glob_t *pglob, |
| Char *pathbuf, *pathend, *pathlim, *pattern; |
size_t *limit) |
| glob_t *pglob; |
|
| size_t *limit; |
|
| { |
{ |
| __gl_stat_t sb; |
__gl_stat_t sb; |
| Char *p, *q; |
Char *p, *q; |
| Line 616 glob2(pathbuf, pathend, pathlim, pattern |
|
| Line 596 glob2(pathbuf, pathend, pathlim, pattern |
|
| if (*pattern == EOS) { /* End of pattern? */ |
if (*pattern == EOS) { /* End of pattern? */ |
| *pathend = EOS; |
*pathend = EOS; |
| if (g_lstat(pathbuf, &sb, pglob)) |
if (g_lstat(pathbuf, &sb, pglob)) |
| return(0); |
return 0; |
| |
|
| if (((pglob->gl_flags & GLOB_MARK) && |
if (((pglob->gl_flags & GLOB_MARK) && |
| pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || |
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || |
| Line 624 glob2(pathbuf, pathend, pathlim, pattern |
|
| Line 604 glob2(pathbuf, pathend, pathlim, pattern |
|
| (g_stat(pathbuf, &sb, pglob) == 0) && |
(g_stat(pathbuf, &sb, pglob) == 0) && |
| S_ISDIR(sb.st_mode)))) { |
S_ISDIR(sb.st_mode)))) { |
| if (pathend >= pathlim) |
if (pathend >= pathlim) |
| return (GLOB_ABORTED); |
return GLOB_ABORTED; |
| *pathend++ = SEP; |
*pathend++ = SEP; |
| *pathend = EOS; |
*pathend = EOS; |
| } |
} |
| ++pglob->gl_matchc; |
++pglob->gl_matchc; |
| return(globextend(pathbuf, pglob, limit)); |
return globextend(pathbuf, pglob, limit); |
| } |
} |
| |
|
| /* Find end of next segment, copy tentatively to pathend. */ |
/* Find end of next segment, copy tentatively to pathend. */ |
| Line 652 glob2(pathbuf, pathend, pathlim, pattern |
|
| Line 632 glob2(pathbuf, pathend, pathlim, pattern |
|
| *pathend++ = *pattern++; |
*pathend++ = *pattern++; |
| } |
} |
| } else /* Need expansion, recurse. */ |
} else /* Need expansion, recurse. */ |
| return(glob3(pathbuf, pathend, pathlim, pattern, p, |
return glob3(pathbuf, pathend, pathlim, pattern, p, |
| pglob, limit)); |
pglob, limit); |
| } |
} |
| /* NOTREACHED */ |
/* NOTREACHED */ |
| } |
} |
| |
|
| static int |
static int |
| glob3(pathbuf, pathend, pathlim, pattern, restpattern, pglob, limit) |
glob3(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, |
| Char *pathbuf, *pathend, *pathlim, *pattern, *restpattern; |
Char *restpattern, glob_t *pglob, size_t *limit) |
| glob_t *pglob; |
|
| size_t *limit; |
|
| { |
{ |
| struct dirent *dp; |
struct dirent *dp; |
| DIR *dirp; |
DIR *dirp; |
| Line 675 glob3(pathbuf, pathend, pathlim, pattern |
|
| Line 653 glob3(pathbuf, pathend, pathlim, pattern |
|
| * and dirent.h as taking pointers to differently typed opaque |
* and dirent.h as taking pointers to differently typed opaque |
| * structures. |
* structures. |
| */ |
*/ |
| struct dirent *(*readdirfunc) __P((void *)); |
struct dirent *(*readdirfunc)(void *); |
| |
|
| _DIAGASSERT(pathbuf != NULL); |
_DIAGASSERT(pathbuf != NULL); |
| _DIAGASSERT(pathend != NULL); |
_DIAGASSERT(pathend != NULL); |
| Line 689 glob3(pathbuf, pathend, pathlim, pattern |
|
| Line 667 glob3(pathbuf, pathend, pathlim, pattern |
|
| if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { |
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { |
| if (pglob->gl_errfunc) { |
if (pglob->gl_errfunc) { |
| if (g_Ctoc(pathbuf, buf, sizeof(buf))) |
if (g_Ctoc(pathbuf, buf, sizeof(buf))) |
| return (GLOB_ABORTED); |
return GLOB_ABORTED; |
| if (pglob->gl_errfunc(buf, errno) || |
if (pglob->gl_errfunc(buf, errno) || |
| pglob->gl_flags & GLOB_ERR) |
pglob->gl_flags & GLOB_ERR) |
| return (GLOB_ABORTED); |
return GLOB_ABORTED; |
| } |
} |
| /* |
/* |
| * Posix/XOpen: glob should return when it encounters a |
* Posix/XOpen: glob should return when it encounters a |
| Line 701 glob3(pathbuf, pathend, pathlim, pattern |
|
| Line 679 glob3(pathbuf, pathend, pathlim, pattern |
|
| * I think that Posix had in mind EPERM... |
* I think that Posix had in mind EPERM... |
| */ |
*/ |
| if (pglob->gl_flags & GLOB_ERR) |
if (pglob->gl_flags & GLOB_ERR) |
| return (GLOB_ABORTED); |
return GLOB_ABORTED; |
| |
|
| return(0); |
return 0; |
| } |
} |
| |
|
| error = 0; |
error = 0; |
| Line 765 glob3(pathbuf, pathend, pathlim, pattern |
|
| Line 743 glob3(pathbuf, pathend, pathlim, pattern |
|
| * Again Posix X/Open issue with regards to error handling. |
* Again Posix X/Open issue with regards to error handling. |
| */ |
*/ |
| if ((error || errno) && (pglob->gl_flags & GLOB_ERR)) |
if ((error || errno) && (pglob->gl_flags & GLOB_ERR)) |
| return (GLOB_ABORTED); |
return GLOB_ABORTED; |
| |
|
| return(error); |
return error; |
| } |
} |
| |
|
| |
|
| Line 786 glob3(pathbuf, pathend, pathlim, pattern |
|
| Line 764 glob3(pathbuf, pathend, pathlim, pattern |
|
| * gl_pathv points to (gl_offs + gl_pathc + 1) items. |
* gl_pathv points to (gl_offs + gl_pathc + 1) items. |
| */ |
*/ |
| static int |
static int |
| globextend(path, pglob, limit) |
globextend(const Char *path, glob_t *pglob, size_t *limit) |
| const Char *path; |
|
| glob_t *pglob; |
|
| size_t *limit; |
|
| { |
{ |
| char **pathv; |
char **pathv; |
| size_t i, newsize, len; |
size_t i, newsize, len; |
| Line 803 globextend(path, pglob, limit) |
|
| Line 778 globextend(path, pglob, limit) |
|
| pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) : |
pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) : |
| malloc(newsize); |
malloc(newsize); |
| if (pathv == NULL) |
if (pathv == NULL) |
| return(GLOB_NOSPACE); |
return GLOB_NOSPACE; |
| |
|
| if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { |
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { |
| /* first time around -- clear initial gl_offs items */ |
/* first time around -- clear initial gl_offs items */ |
| Line 820 globextend(path, pglob, limit) |
|
| Line 795 globextend(path, pglob, limit) |
|
| if ((copy = malloc(len)) != NULL) { |
if ((copy = malloc(len)) != NULL) { |
| if (g_Ctoc(path, copy, len)) { |
if (g_Ctoc(path, copy, len)) { |
| free(copy); |
free(copy); |
| return(GLOB_ABORTED); |
return GLOB_ABORTED; |
| } |
} |
| pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; |
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; |
| } |
} |
| Line 828 globextend(path, pglob, limit) |
|
| Line 803 globextend(path, pglob, limit) |
|
| |
|
| if ((pglob->gl_flags & GLOB_LIMIT) && (newsize + *limit) >= ARG_MAX) { |
if ((pglob->gl_flags & GLOB_LIMIT) && (newsize + *limit) >= ARG_MAX) { |
| errno = 0; |
errno = 0; |
| return(GLOB_NOSPACE); |
return GLOB_NOSPACE; |
| } |
} |
| |
|
| return(copy == NULL ? GLOB_NOSPACE : 0); |
return copy == NULL ? GLOB_NOSPACE : 0; |
| } |
} |
| |
|
| |
|
| Line 840 globextend(path, pglob, limit) |
|
| Line 815 globextend(path, pglob, limit) |
|
| * pattern causes a recursion level. |
* pattern causes a recursion level. |
| */ |
*/ |
| static int |
static int |
| match(name, pat, patend) |
match(Char *name, Char *pat, Char *patend) |
| Char *name, *pat, *patend; |
|
| { |
{ |
| int ok, negate_range; |
int ok, negate_range; |
| Char c, k; |
Char c, k; |
| Line 855 match(name, pat, patend) |
|
| Line 829 match(name, pat, patend) |
|
| switch (c & M_MASK) { |
switch (c & M_MASK) { |
| case M_ALL: |
case M_ALL: |
| if (pat == patend) |
if (pat == patend) |
| return(1); |
return 1; |
| do |
do |
| if (match(name, pat, patend)) |
if (match(name, pat, patend)) |
| return(1); |
return 1; |
| while (*name++ != EOS); |
while (*name++ != EOS); |
| return(0); |
return 0; |
| case M_ONE: |
case M_ONE: |
| if (*name++ == EOS) |
if (*name++ == EOS) |
| return(0); |
return 0; |
| break; |
break; |
| case M_SET: |
case M_SET: |
| ok = 0; |
ok = 0; |
| if ((k = *name++) == EOS) |
if ((k = *name++) == EOS) |
| return(0); |
return 0; |
| if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) |
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) |
| ++pat; |
++pat; |
| while (((c = *pat++) & M_MASK) != M_END) |
while (((c = *pat++) & M_MASK) != M_END) |
| Line 879 match(name, pat, patend) |
|
| Line 853 match(name, pat, patend) |
|
| } else if (c == k) |
} else if (c == k) |
| ok = 1; |
ok = 1; |
| if (ok == negate_range) |
if (ok == negate_range) |
| return(0); |
return 0; |
| break; |
break; |
| default: |
default: |
| if (*name++ != c) |
if (*name++ != c) |
| return(0); |
return 0; |
| break; |
break; |
| } |
} |
| } |
} |
| return(*name == EOS); |
return *name == EOS; |
| } |
} |
| |
|
| /* Free allocated data belonging to a glob_t structure. */ |
/* Free allocated data belonging to a glob_t structure. */ |
| void |
void |
| globfree(pglob) |
globfree(glob_t *pglob) |
| glob_t *pglob; |
|
| { |
{ |
| size_t i; |
size_t i; |
| char **pp; |
char **pp; |
|
|
| } |
} |
| |
|
| static DIR * |
static DIR * |
| g_opendir(str, pglob) |
g_opendir(Char *str, glob_t *pglob) |
| Char *str; |
|
| glob_t *pglob; |
|
| { |
{ |
| char buf[MAXPATHLEN]; |
char buf[MAXPATHLEN]; |
| |
|
| Line 929 g_opendir(str, pglob) |
|
| Line 900 g_opendir(str, pglob) |
|
| } |
} |
| |
|
| if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
| return((*pglob->gl_opendir)(buf)); |
return (*pglob->gl_opendir)(buf); |
| |
|
| return(opendir(buf)); |
return opendir(buf); |
| } |
} |
| |
|
| static int |
static int |
| g_lstat(fn, sb, pglob) |
g_lstat(Char *fn, __gl_stat_t *sb, glob_t *pglob) |
| Char *fn; |
|
| __gl_stat_t *sb; |
|
| glob_t *pglob; |
|
| { |
{ |
| char buf[MAXPATHLEN]; |
char buf[MAXPATHLEN]; |
| |
|
| Line 949 g_lstat(fn, sb, pglob) |
|
| Line 917 g_lstat(fn, sb, pglob) |
|
| if (g_Ctoc(fn, buf, sizeof(buf))) |
if (g_Ctoc(fn, buf, sizeof(buf))) |
| return -1; |
return -1; |
| if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
| return((*pglob->gl_lstat)(buf, sb)); |
return (*pglob->gl_lstat)(buf, sb); |
| return(lstat(buf, sb)); |
return lstat(buf, sb); |
| } |
} |
| |
|
| static int |
static int |
| g_stat(fn, sb, pglob) |
g_stat(Char *fn, __gl_stat_t *sb, glob_t *pglob) |
| Char *fn; |
|
| __gl_stat_t *sb; |
|
| glob_t *pglob; |
|
| { |
{ |
| char buf[MAXPATHLEN]; |
char buf[MAXPATHLEN]; |
| |
|
| Line 968 g_stat(fn, sb, pglob) |
|
| Line 933 g_stat(fn, sb, pglob) |
|
| if (g_Ctoc(fn, buf, sizeof(buf))) |
if (g_Ctoc(fn, buf, sizeof(buf))) |
| return -1; |
return -1; |
| if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
if (pglob->gl_flags & GLOB_ALTDIRFUNC) |
| return((*pglob->gl_stat)(buf, sb)); |
return (*pglob->gl_stat)(buf, sb); |
| return(stat(buf, sb)); |
return stat(buf, sb); |
| } |
} |
| |
|
| static Char * |
static Char * |
| g_strchr(str, ch) |
g_strchr(const Char *str, int ch) |
| const Char *str; |
|
| int ch; |
|
| { |
{ |
| |
|
| _DIAGASSERT(str != NULL); |
_DIAGASSERT(str != NULL); |
| Line 988 g_strchr(str, ch) |
|
| Line 951 g_strchr(str, ch) |
|
| } |
} |
| |
|
| static int |
static int |
| g_Ctoc(str, buf, len) |
g_Ctoc(const Char *str, char *buf, size_t len) |
| const Char *str; |
|
| char *buf; |
|
| size_t len; |
|
| { |
{ |
| char *dc; |
char *dc; |
| |
|
| Line 1009 g_Ctoc(str, buf, len) |
|
| Line 969 g_Ctoc(str, buf, len) |
|
| |
|
| #ifdef DEBUG |
#ifdef DEBUG |
| static void |
static void |
| qprintf(str, s) |
qprintf(const char *str, Char *s) |
| const char *str; |
|
| Char *s; |
|
| { |
{ |
| Char *p; |
Char *p; |
| |
|