123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925 |
- #ifdef PHP_WIN32
- #if _MSC_VER < 1800
- # define _POSIX_
- # include <limits.h>
- # undef _POSIX_
- #else
- # ifndef ARG_MAX
- # define ARG_MAX 14500
- # endif
- #endif
- #endif
- #include "php.h"
- #include <sys/stat.h>
- #include <ctype.h>
- #ifndef PHP_WIN32
- #include <sys/param.h>
- #include <dirent.h>
- #include <pwd.h>
- #include <unistd.h>
- #endif
- #include <errno.h>
- #include "glob.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define DOLLAR '$'
- #define DOT '.'
- #define EOS '\0'
- #define LBRACKET '['
- #define NOT '!'
- #define QUESTION '?'
- #define QUOTE '\\'
- #define RANGE '-'
- #define RBRACKET ']'
- #define SEP DEFAULT_SLASH
- #define STAR '*'
- #define TILDE '~'
- #define UNDERSCORE '_'
- #define LBRACE '{'
- #define RBRACE '}'
- #define SLASH '/'
- #define COMMA ','
- #ifndef DEBUG
- #define M_QUOTE 0x8000
- #define M_PROTECT 0x4000
- #define M_MASK 0xffff
- #define M_ASCII 0x00ff
- typedef u_short Char;
- #else
- #define M_QUOTE 0x80
- #define M_PROTECT 0x40
- #define M_MASK 0xff
- #define M_ASCII 0x7f
- typedef char Char;
- #endif
- #define CHAR(c) ((Char)((c)&M_ASCII))
- #define META(c) ((Char)((c)|M_QUOTE))
- #define M_ALL META('*')
- #define M_END META(']')
- #define M_NOT META('!')
- #define M_ONE META('?')
- #define M_RNG META('-')
- #define M_SET META('[')
- #define ismeta(c) (((c)&M_QUOTE) != 0)
- static int compare(const void *, const void *);
- static int g_Ctoc(const Char *, char *, u_int);
- static int g_lstat(Char *, zend_stat_t *, glob_t *);
- static DIR *g_opendir(Char *, glob_t *);
- static Char *g_strchr(Char *, int);
- static int g_stat(Char *, zend_stat_t *, glob_t *);
- static int glob0(const Char *, glob_t *);
- static int glob1(Char *, Char *, glob_t *, size_t *);
- static int glob2(Char *, Char *, Char *, Char *, Char *, Char *,
- glob_t *, size_t *);
- static int glob3(Char *, Char *, Char *, Char *, Char *, Char *,
- Char *, 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 *);
- static int globexp2(const Char *, const Char *, glob_t *, int *);
- static int match(Char *, Char *, Char *);
- #ifdef DEBUG
- static void qprintf(const char *, Char *);
- #endif
- PHPAPI int
- glob(pattern, flags, errfunc, pglob)
- const char *pattern;
- int flags, (*errfunc)(const char *, int);
- glob_t *pglob;
- {
- const u_char *patnext;
- int c;
- Char *bufnext, *bufend, patbuf[MAXPATHLEN];
- #ifdef PHP_WIN32
-
- flags |= GLOB_NOESCAPE;
- #endif
- patnext = (u_char *) pattern;
- if (!(flags & GLOB_APPEND)) {
- pglob->gl_pathc = 0;
- pglob->gl_pathv = NULL;
- if (!(flags & GLOB_DOOFFS))
- pglob->gl_offs = 0;
- }
- pglob->gl_flags = flags & ~GLOB_MAGCHAR;
- pglob->gl_errfunc = errfunc;
- pglob->gl_matchc = 0;
- bufnext = patbuf;
- bufend = bufnext + MAXPATHLEN - 1;
- if (flags & GLOB_NOESCAPE)
- while (bufnext < bufend && (c = *patnext++) != EOS)
- *bufnext++ = c;
- else {
-
- while (bufnext < bufend && (c = *patnext++) != EOS)
- if (c == QUOTE) {
- if ((c = *patnext++) == EOS) {
- c = QUOTE;
- --patnext;
- }
- *bufnext++ = c | M_PROTECT;
- } else
- *bufnext++ = c;
- }
- *bufnext = EOS;
- if (flags & GLOB_BRACE)
- return globexp1(patbuf, pglob);
- else
- return glob0(patbuf, pglob);
- }
- static int
- globexp1(pattern, pglob)
- const Char *pattern;
- glob_t *pglob;
- {
- const Char* ptr = pattern;
- int rv;
-
- if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
- return glob0(pattern, pglob);
- while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
- if (!globexp2(ptr, pattern, pglob, &rv))
- return rv;
- return glob0(pattern, pglob);
- }
- static int
- globexp2(ptr, pattern, pglob, rv)
- const Char *ptr, *pattern;
- glob_t *pglob;
- int *rv;
- {
- int i;
- Char *lm, *ls;
- const Char *pe, *pm, *pl;
- Char patbuf[MAXPATHLEN];
-
- for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
- ;
- *lm = EOS;
- ls = lm;
-
- for (i = 0, pe = ++ptr; *pe; pe++)
- if (*pe == LBRACKET) {
-
- for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
- ;
- if (*pe == EOS) {
-
- pe = pm;
- }
- } else if (*pe == LBRACE)
- i++;
- else if (*pe == RBRACE) {
- if (i == 0)
- break;
- i--;
- }
-
- if (i != 0 || *pe == EOS) {
- *rv = glob0(patbuf, pglob);
- return 0;
- }
- for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
- const Char *pb;
- switch (*pm) {
- case LBRACKET:
-
- for (pb = pm++; *pm != RBRACKET && *pm != EOS; pm++)
- ;
- if (*pm == EOS) {
-
- pm = pb;
- }
- break;
- case LBRACE:
- i++;
- break;
- case RBRACE:
- if (i) {
- i--;
- break;
- }
-
- case COMMA:
- if (i && *pm == COMMA)
- break;
- else {
-
- for (lm = ls; (pl < pm); *lm++ = *pl++)
- ;
-
- for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
- ;
-
- #ifdef DEBUG
- qprintf("globexp2:", patbuf);
- #endif
- *rv = globexp1(patbuf, pglob);
-
- pl = pm + 1;
- }
- break;
- default:
- break;
- }
- }
- *rv = 0;
- return 0;
- }
- static const Char *
- globtilde(pattern, patbuf, patbuf_len, pglob)
- const Char *pattern;
- Char *patbuf;
- size_t patbuf_len;
- glob_t *pglob;
- {
- #ifndef PHP_WIN32
- struct passwd *pwd;
- #endif
- char *h;
- const Char *p;
- Char *b, *eb;
- if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
- return pattern;
-
- eb = &patbuf[patbuf_len - 1];
- for (p = pattern + 1, h = (char *) patbuf;
- h < (char *)eb && *p && *p != SLASH; *h++ = (char) *p++)
- ;
- *h = EOS;
- #if 0
- if (h == (char *)eb)
- return what;
- #endif
- if (((char *) patbuf)[0] == EOS) {
-
- if ((h = getenv("HOME")) == NULL) {
- #ifndef PHP_WIN32
- if ((pwd = getpwuid(getuid())) == NULL)
- return pattern;
- else
- h = pwd->pw_dir;
- #else
- return pattern;
- #endif
- }
- } else {
-
- #ifndef PHP_WIN32
- if ((pwd = getpwnam((char*) patbuf)) == NULL)
- return pattern;
- else
- h = pwd->pw_dir;
- #else
- return pattern;
- #endif
- }
-
- for (b = patbuf; b < eb && *h; *b++ = *h++)
- ;
-
- while (b < eb && (*b++ = *p++) != EOS)
- ;
- *b = EOS;
- return patbuf;
- }
- static int
- glob0(pattern, pglob)
- const Char *pattern;
- glob_t *pglob;
- {
- const Char *qpatnext;
- int c, err, oldpathc;
- Char *bufnext, patbuf[MAXPATHLEN];
- size_t limit = 0;
- qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
- oldpathc = pglob->gl_pathc;
- bufnext = patbuf;
-
- while ((c = *qpatnext++) != EOS) {
- switch (c) {
- case LBRACKET:
- c = *qpatnext;
- if (c == NOT)
- ++qpatnext;
- if (*qpatnext == EOS ||
- g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
- *bufnext++ = LBRACKET;
- if (c == NOT)
- --qpatnext;
- break;
- }
- *bufnext++ = M_SET;
- if (c == NOT)
- *bufnext++ = M_NOT;
- c = *qpatnext++;
- do {
- *bufnext++ = CHAR(c);
- if (*qpatnext == RANGE &&
- (c = qpatnext[1]) != RBRACKET) {
- *bufnext++ = M_RNG;
- *bufnext++ = CHAR(c);
- qpatnext += 2;
- }
- } while ((c = *qpatnext++) != RBRACKET);
- pglob->gl_flags |= GLOB_MAGCHAR;
- *bufnext++ = M_END;
- break;
- case QUESTION:
- pglob->gl_flags |= GLOB_MAGCHAR;
- *bufnext++ = M_ONE;
- break;
- case STAR:
- pglob->gl_flags |= GLOB_MAGCHAR;
-
- if (bufnext == patbuf || bufnext[-1] != M_ALL)
- *bufnext++ = M_ALL;
- break;
- default:
- *bufnext++ = CHAR(c);
- break;
- }
- }
- *bufnext = EOS;
- #ifdef DEBUG
- qprintf("glob0:", patbuf);
- #endif
- if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0)
- return(err);
-
- if (pglob->gl_pathc == oldpathc) {
- if ((pglob->gl_flags & GLOB_NOCHECK) ||
- ((pglob->gl_flags & GLOB_NOMAGIC) &&
- !(pglob->gl_flags & GLOB_MAGCHAR)))
- return(globextend(pattern, pglob, &limit));
- else
- return(GLOB_NOMATCH);
- }
- if (!(pglob->gl_flags & GLOB_NOSORT))
- qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
- pglob->gl_pathc - oldpathc, sizeof(char *), compare);
- return(0);
- }
- static int
- compare(const void *p, const void *q)
- {
- return(strcmp(*(char **)p, *(char **)q));
- }
- static int
- glob1(pattern, pattern_last, pglob, limitp)
- Char *pattern, *pattern_last;
- glob_t *pglob;
- size_t *limitp;
- {
- Char pathbuf[MAXPATHLEN];
-
- if (*pattern == EOS)
- return(0);
- return(glob2(pathbuf, pathbuf+MAXPATHLEN-1,
- pathbuf, pathbuf+MAXPATHLEN-1,
- pattern, pattern_last, pglob, limitp));
- }
- static int
- glob2(pathbuf, pathbuf_last, pathend, pathend_last, pattern,
- pattern_last, pglob, limitp)
- Char *pathbuf, *pathbuf_last, *pathend, *pathend_last;
- Char *pattern, *pattern_last;
- glob_t *pglob;
- size_t *limitp;
- {
- zend_stat_t sb;
- Char *p, *q;
- int anymeta;
-
- for (anymeta = 0;;) {
- if (*pattern == EOS) {
- *pathend = EOS;
- if (g_lstat(pathbuf, &sb, pglob))
- return(0);
- if (((pglob->gl_flags & GLOB_MARK) &&
- !IS_SLASH(pathend[-1])) && (S_ISDIR(sb.st_mode) ||
- (S_ISLNK(sb.st_mode) &&
- (g_stat(pathbuf, &sb, pglob) == 0) &&
- S_ISDIR(sb.st_mode)))) {
- if (pathend+1 > pathend_last)
- return (1);
- *pathend++ = SEP;
- *pathend = EOS;
- }
- ++pglob->gl_matchc;
- return(globextend(pathbuf, pglob, limitp));
- }
-
- q = pathend;
- p = pattern;
- while (*p != EOS && !IS_SLASH(*p)) {
- if (ismeta(*p))
- anymeta = 1;
- if (q+1 > pathend_last)
- return (1);
- *q++ = *p++;
- }
- if (!anymeta) {
- pathend = q;
- pattern = p;
- while (IS_SLASH(*pattern)) {
- if (pathend+1 > pathend_last)
- return (1);
- *pathend++ = *pattern++;
- }
- } else
-
- return(glob3(pathbuf, pathbuf_last, pathend,
- pathend_last, pattern, pattern_last,
- p, pattern_last, pglob, limitp));
- }
-
- }
- static int
- glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last,
- restpattern, restpattern_last, pglob, limitp)
- Char *pathbuf, *pathbuf_last, *pathend, *pathend_last;
- Char *pattern, *pattern_last, *restpattern, *restpattern_last;
- glob_t *pglob;
- size_t *limitp;
- {
- register struct dirent *dp;
- DIR *dirp;
- int err;
-
- struct dirent *(*readdirfunc)();
- if (pathend > pathend_last)
- return (1);
- *pathend = EOS;
- errno = 0;
- if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
-
- if (pglob->gl_errfunc) {
- char buf[MAXPATHLEN];
- if (g_Ctoc(pathbuf, buf, sizeof(buf)))
- return(GLOB_ABORTED);
- if (pglob->gl_errfunc(buf, errno) ||
- pglob->gl_flags & GLOB_ERR)
- return(GLOB_ABORTED);
- }
- return(0);
- }
- err = 0;
-
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- readdirfunc = pglob->gl_readdir;
- else
- readdirfunc = readdir;
- while ((dp = (*readdirfunc)(dirp))) {
- register u_char *sc;
- register Char *dc;
-
- if (dp->d_name[0] == DOT && *pattern != DOT)
- continue;
- dc = pathend;
- sc = (u_char *) dp->d_name;
- while (dc < pathend_last && (*dc++ = *sc++) != EOS)
- ;
- if (dc >= pathend_last) {
- *dc = EOS;
- err = 1;
- break;
- }
- if (!match(pathend, pattern, restpattern)) {
- *pathend = EOS;
- continue;
- }
- err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
- restpattern, restpattern_last, pglob, limitp);
- if (err)
- break;
- }
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- (*pglob->gl_closedir)(dirp);
- else
- closedir(dirp);
- return(err);
- }
- static int
- globextend(path, pglob, limitp)
- const Char *path;
- glob_t *pglob;
- size_t *limitp;
- {
- register char **pathv;
- u_int newsize, len;
- char *copy;
- const Char *p;
- newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
- pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) :
- malloc(newsize);
- if (pathv == NULL) {
- if (pglob->gl_pathv) {
- free(pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- }
- return(GLOB_NOSPACE);
- }
- if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
- register int i;
-
- pathv += pglob->gl_offs;
- for (i = pglob->gl_offs; --i >= 0; )
- *--pathv = NULL;
- }
- pglob->gl_pathv = pathv;
- for (p = path; *p++;)
- ;
- len = (u_int)(p - path);
- *limitp += len;
- if ((copy = malloc(len)) != NULL) {
- if (g_Ctoc(path, copy, len)) {
- free(copy);
- return(GLOB_NOSPACE);
- }
- pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
- }
- pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
- if ((pglob->gl_flags & GLOB_LIMIT) &&
- newsize + *limitp >= ARG_MAX) {
- errno = 0;
- return(GLOB_NOSPACE);
- }
- return(copy == NULL ? GLOB_NOSPACE : 0);
- }
- static int
- match(name, pat, patend)
- register Char *name, *pat, *patend;
- {
- int ok, negate_range;
- Char c, k;
- while (pat < patend) {
- c = *pat++;
- switch (c & M_MASK) {
- case M_ALL:
- if (pat == patend)
- return(1);
- do
- if (match(name, pat, patend))
- return(1);
- while (*name++ != EOS)
- ;
- return(0);
- case M_ONE:
- if (*name++ == EOS)
- return(0);
- break;
- case M_SET:
- ok = 0;
- if ((k = *name++) == EOS)
- return(0);
- if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
- ++pat;
- while (((c = *pat++) & M_MASK) != M_END)
- if ((*pat & M_MASK) == M_RNG) {
- if (c <= k && k <= pat[1])
- ok = 1;
- pat += 2;
- } else if (c == k)
- ok = 1;
- if (ok == negate_range)
- return(0);
- break;
- default:
- if (*name++ != c)
- return(0);
- break;
- }
- }
- return(*name == EOS);
- }
- PHPAPI void
- globfree(pglob)
- glob_t *pglob;
- {
- register int i;
- register char **pp;
- if (pglob->gl_pathv != NULL) {
- pp = pglob->gl_pathv + pglob->gl_offs;
- for (i = pglob->gl_pathc; i--; ++pp)
- if (*pp)
- free(*pp);
- free(pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- }
- }
- static DIR *
- g_opendir(str, pglob)
- register Char *str;
- glob_t *pglob;
- {
- char buf[MAXPATHLEN];
- if (!*str)
- strlcpy(buf, ".", sizeof(buf));
- else {
- if (g_Ctoc(str, buf, sizeof(buf)))
- return(NULL);
- }
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return((*pglob->gl_opendir)(buf));
- return(opendir(buf));
- }
- static int
- g_lstat(fn, sb, pglob)
- register Char *fn;
- zend_stat_t *sb;
- glob_t *pglob;
- {
- char buf[MAXPATHLEN];
- if (g_Ctoc(fn, buf, sizeof(buf)))
- return(-1);
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return((*pglob->gl_lstat)(buf, sb));
- return(php_sys_lstat(buf, sb));
- }
- static int
- g_stat(fn, sb, pglob)
- register Char *fn;
- zend_stat_t *sb;
- glob_t *pglob;
- {
- char buf[MAXPATHLEN];
- if (g_Ctoc(fn, buf, sizeof(buf)))
- return(-1);
- if (pglob->gl_flags & GLOB_ALTDIRFUNC)
- return((*pglob->gl_stat)(buf, sb));
- return(php_sys_stat(buf, sb));
- }
- static Char *
- g_strchr(str, ch)
- Char *str;
- int ch;
- {
- do {
- if (*str == ch)
- return (str);
- } while (*str++);
- return (NULL);
- }
- static int
- g_Ctoc(str, buf, len)
- register const Char *str;
- char *buf;
- u_int len;
- {
- while (len--) {
- if ((*buf++ = (char) *str++) == EOS)
- return (0);
- }
- return (1);
- }
- #ifdef DEBUG
- static void
- qprintf(str, s)
- const char *str;
- register Char *s;
- {
- register Char *p;
- (void)printf("%s:\n", str);
- for (p = s; *p; p++)
- (void)printf("%c", CHAR(*p));
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", ismeta(*p) ? '_' : ' ');
- (void)printf("\n");
- }
- #endif
|