Changeset View
Changeset View
Standalone View
Standalone View
lib/libc/gen/glob.c
Show First 20 Lines • Show All 185 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
int | int | ||||
glob(const char * __restrict pattern, int flags, | glob(const char * __restrict pattern, int flags, | ||||
int (*errfunc)(const char *, int), glob_t * __restrict pglob) | int (*errfunc)(const char *, int), glob_t * __restrict pglob) | ||||
{ | { | ||||
struct glob_limit limit = { 0, 0, 0, 0, 0 }; | struct glob_limit limit = { 0, 0, 0, 0, 0 }; | ||||
const char *patnext; | const char *patnext; | ||||
Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot; | Char *bufnext, *bufend, *patbuf, prot; | ||||
mbstate_t mbs; | mbstate_t mbs; | ||||
wchar_t wc; | wchar_t wc; | ||||
size_t clen; | size_t clen; | ||||
int too_long; | int too_long, error; | ||||
error = 0; | |||||
patbuf = malloc(MAXPATHLEN * sizeof(*patbuf)); | |||||
if (patbuf == NULL) | |||||
return (GLOB_NOSPACE); | |||||
patnext = pattern; | patnext = pattern; | ||||
if (!(flags & GLOB_APPEND)) { | if (!(flags & GLOB_APPEND)) { | ||||
pglob->gl_pathc = 0; | pglob->gl_pathc = 0; | ||||
pglob->gl_pathv = NULL; | pglob->gl_pathv = NULL; | ||||
if (!(flags & GLOB_DOOFFS)) | if (!(flags & GLOB_DOOFFS)) | ||||
pglob->gl_offs = 0; | pglob->gl_offs = 0; | ||||
} | } | ||||
if (flags & GLOB_LIMIT) { | if (flags & GLOB_LIMIT) { | ||||
limit.l_path_lim = pglob->gl_matchc; | limit.l_path_lim = pglob->gl_matchc; | ||||
if (limit.l_path_lim == 0) | if (limit.l_path_lim == 0) | ||||
limit.l_path_lim = GLOB_LIMIT_PATH; | limit.l_path_lim = GLOB_LIMIT_PATH; | ||||
} | } | ||||
pglob->gl_flags = flags & ~GLOB_MAGCHAR; | pglob->gl_flags = flags & ~GLOB_MAGCHAR; | ||||
pglob->gl_errfunc = errfunc; | pglob->gl_errfunc = errfunc; | ||||
pglob->gl_matchc = 0; | pglob->gl_matchc = 0; | ||||
bufnext = patbuf; | bufnext = patbuf; | ||||
bufend = bufnext + MAXPATHLEN - 1; | bufend = bufnext + MAXPATHLEN - 1; | ||||
too_long = 1; | too_long = 1; | ||||
if (flags & GLOB_NOESCAPE) { | if (flags & GLOB_NOESCAPE) { | ||||
memset(&mbs, 0, sizeof(mbs)); | memset(&mbs, 0, sizeof(mbs)); | ||||
while (bufnext <= bufend) { | while (bufnext <= bufend) { | ||||
clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); | clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); | ||||
if (clen == (size_t)-1 || clen == (size_t)-2) | if (clen == (size_t)-1 || clen == (size_t)-2) { | ||||
return (err_nomatch(pglob, &limit, pattern)); | error = err_nomatch(pglob, &limit, pattern); | ||||
else if (clen == 0) { | goto out; | ||||
} else if (clen == 0) { | |||||
too_long = 0; | too_long = 0; | ||||
break; | break; | ||||
} | } | ||||
*bufnext++ = wc; | *bufnext++ = wc; | ||||
patnext += clen; | patnext += clen; | ||||
} | } | ||||
} else { | } else { | ||||
/* Protect the quoted characters. */ | /* Protect the quoted characters. */ | ||||
memset(&mbs, 0, sizeof(mbs)); | memset(&mbs, 0, sizeof(mbs)); | ||||
while (bufnext <= bufend) { | while (bufnext <= bufend) { | ||||
if (*patnext == '\\') { | if (*patnext == '\\') { | ||||
if (*++patnext == '\0') { | if (*++patnext == '\0') { | ||||
*bufnext++ = QUOTE; | *bufnext++ = QUOTE; | ||||
continue; | continue; | ||||
} | } | ||||
prot = M_PROTECT; | prot = M_PROTECT; | ||||
} else | } else | ||||
prot = 0; | prot = 0; | ||||
clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); | clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); | ||||
if (clen == (size_t)-1 || clen == (size_t)-2) | if (clen == (size_t)-1 || clen == (size_t)-2) { | ||||
return (err_nomatch(pglob, &limit, pattern)); | error = err_nomatch(pglob, &limit, pattern); | ||||
else if (clen == 0) { | goto out; | ||||
} else if (clen == 0) { | |||||
too_long = 0; | too_long = 0; | ||||
break; | break; | ||||
} | } | ||||
*bufnext++ = wc | prot; | *bufnext++ = wc | prot; | ||||
patnext += clen; | patnext += clen; | ||||
} | } | ||||
} | } | ||||
if (too_long) | if (too_long) { | ||||
return (err_nomatch(pglob, &limit, pattern)); | error = err_nomatch(pglob, &limit, pattern); | ||||
goto out; | |||||
} | |||||
*bufnext = EOS; | *bufnext = EOS; | ||||
if (flags & GLOB_BRACE) | if (flags & GLOB_BRACE) | ||||
return (globexp0(patbuf, pglob, &limit, pattern)); | error = globexp0(patbuf, pglob, &limit, pattern); | ||||
else | else | ||||
return (glob0(patbuf, pglob, &limit, pattern)); | error = glob0(patbuf, pglob, &limit, pattern); | ||||
out: | |||||
free(patbuf); | |||||
return (error); | |||||
} | } | ||||
static int | static int | ||||
globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, | globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, | ||||
const char *origpat) { | const char *origpat) { | ||||
int rv; | int rv; | ||||
size_t oldpathc; | size_t oldpathc; | ||||
▲ Show 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | |||||
* if things went well, nonzero if errors occurred. | * if things went well, nonzero if errors occurred. | ||||
*/ | */ | ||||
static int | static int | ||||
glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, | glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, | ||||
const char *origpat) { | const char *origpat) { | ||||
const Char *qpatnext; | const Char *qpatnext; | ||||
int err; | int err; | ||||
size_t oldpathc; | size_t oldpathc; | ||||
Char *bufnext, c, patbuf[MAXPATHLEN]; | Char *bufnext, c, *patbuf; | ||||
patbuf = malloc(MAXPATHLEN * sizeof(*patbuf)); | |||||
if (patbuf == NULL) | |||||
return (GLOB_NOSPACE); | |||||
qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); | qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); | ||||
if (qpatnext == NULL) { | if (qpatnext == NULL) { | ||||
errno = E2BIG; | errno = E2BIG; | ||||
return (GLOB_NOSPACE); | err = GLOB_NOSPACE; | ||||
goto out; | |||||
} | } | ||||
oldpathc = pglob->gl_pathc; | oldpathc = pglob->gl_pathc; | ||||
bufnext = patbuf; | bufnext = patbuf; | ||||
/* We don't need to check for buffer overflow any more. */ | /* We don't need to check for buffer overflow any more. */ | ||||
while ((c = *qpatnext++) != EOS) { | while ((c = *qpatnext++) != EOS) { | ||||
switch (c) { | switch (c) { | ||||
case LBRACKET: | case LBRACKET: | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | while ((c = *qpatnext++) != EOS) { | ||||
} | } | ||||
} | } | ||||
*bufnext = EOS; | *bufnext = EOS; | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
qprintf("glob0:", patbuf); | qprintf("glob0:", patbuf); | ||||
#endif | #endif | ||||
if ((err = glob1(patbuf, pglob, limit)) != 0) | if ((err = glob1(patbuf, pglob, limit)) != 0) | ||||
return(err); | goto out; | ||||
if (origpat != NULL) | if (origpat != NULL) | ||||
return (globfinal(pglob, limit, oldpathc, origpat)); | err = globfinal(pglob, limit, oldpathc, origpat); | ||||
return (0); | out: | ||||
free(patbuf); | |||||
return (err); | |||||
} | } | ||||
static int | static int | ||||
globfinal(glob_t *pglob, struct glob_limit *limit, size_t oldpathc, | globfinal(glob_t *pglob, struct glob_limit *limit, size_t oldpathc, | ||||
const char *origpat) { | const char *origpat) { | ||||
if (pglob->gl_pathc == oldpathc) | if (pglob->gl_pathc == oldpathc) | ||||
return (err_nomatch(pglob, limit, origpat)); | return (err_nomatch(pglob, limit, origpat)); | ||||
▲ Show 20 Lines • Show All 505 Lines • Show Last 20 Lines |