|
Message-Id: <20190801180113.24330-2-ismael@iodev.co.uk> Date: Thu, 1 Aug 2019 20:01:13 +0200 From: Ismael Luceno <ismael@...ev.co.uk> To: musl@...ts.openwall.com Cc: Ismael Luceno <ismael@...ev.co.uk> Subject: [PATCH v2] glob: implement GLOB_ALTDIRFUNC et al Signed-off-by: Ismael Luceno <ismael@...ev.co.uk> --- include/glob.h | 8 +++++++- src/regex/glob.c | 45 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/include/glob.h b/include/glob.h index 0ff70bdfeef2..0db4780f6a00 100644 --- a/include/glob.h +++ b/include/glob.h @@ -16,7 +16,12 @@ typedef struct { char **gl_pathv; size_t gl_offs; int __dummy1; - void *__dummy2[5]; + + void (*gl_closedir)(void *); + struct dirent *(*gl_readdir)(void *); + void *(*gl_opendir)(const char *); + int (*gl_lstat)(const char *__restrict, struct stat *__restrict); + int (*gl_stat)(const char *__restrict, struct stat *__restrict); } glob_t; int glob(const char *__restrict, int, int (*)(const char *, int), glob_t *__restrict); @@ -31,6 +36,7 @@ void globfree(glob_t *); #define GLOB_NOESCAPE 0x40 #define GLOB_PERIOD 0x80 +#define GLOB_ALTDIRFUNC 0x0200 #define GLOB_NOMAGIC 0x0800 #define GLOB_TILDE 0x1000 #define GLOB_TILDE_CHECK 0x4000 diff --git a/src/regex/glob.c b/src/regex/glob.c index 0ccd9759c5e7..846ab3d0fcdd 100644 --- a/src/regex/glob.c +++ b/src/regex/glob.c @@ -1,7 +1,7 @@ #define _BSD_SOURCE +#include <sys/stat.h> #include <glob.h> #include <fnmatch.h> -#include <sys/stat.h> #include <dirent.h> #include <limits.h> #include <string.h> @@ -11,6 +11,14 @@ #include <unistd.h> #include <pwd.h> +struct dirfn { + void (*closedir)(void *); + struct dirent *(*readdir)(void *); + void *(*opendir)(const char *); + int (*lstat)(const char *restrict, struct stat *restrict); + int (*stat)(const char *restrict, struct stat *restrict); +}; + struct match { struct match *next; @@ -32,7 +40,7 @@ static int append(struct match **tail, const char *name, size_t len, int mark) return 0; } -static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (*errfunc)(const char *path, int err), struct match **tail) +static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (*errfunc)(const char *path, int err), const struct dirfn * const restrict dirfn, struct match **tail) { /* If GLOB_MARK is unused, we don't care about type. */ if (!type && !(flags & GLOB_MARK)) type = DT_REG; @@ -96,7 +104,7 @@ static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (* * determine its type. */ struct stat st; if ((flags & GLOB_MARK) && type==DT_LNK) type = 0; - if (!type && stat(buf, &st)) { + if (!type && dirfn->stat(buf, &st)) { if (errno!=ENOENT && (errfunc(buf, errno) || (flags & GLOB_ERR))) return GLOB_ABORTED; return 0; @@ -117,7 +125,7 @@ static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (* saved_sep = '\\'; } } - DIR *dir = opendir(pos ? buf : "."); + DIR *dir = dirfn->opendir(pos ? buf : "."); if (!dir) { if (errfunc(buf, errno) || (flags & GLOB_ERR)) return GLOB_ABORTED; @@ -125,7 +133,7 @@ static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (* } int old_errno = errno; struct dirent *de; - while (errno=0, de=readdir(dir)) { + while (errno=0, de=dirfn->readdir(dir)) { /* Quickly skip non-directories when there's pattern left. */ if (p2 && de->d_type && de->d_type!=DT_DIR && de->d_type!=DT_LNK) continue; @@ -150,15 +158,15 @@ static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (* memcpy(buf+pos, de->d_name, l+1); if (p2) *p2 = saved_sep; - int r = do_glob(buf, pos+l, de->d_type, p2 ? p2 : "", flags, errfunc, tail); + int r = do_glob(buf, pos+l, de->d_type, p2 ? p2 : "", flags, errfunc, dirfn, tail); if (r) { - closedir(dir); + dirfn->closedir(dir); return r; } } int readerr = errno; if (p2) *p2 = saved_sep; - closedir(dir); + dirfn->closedir(dir); if (readerr && (errfunc(buf, errno) || (flags & GLOB_ERR))) return GLOB_ABORTED; errno = old_errno; @@ -217,6 +225,10 @@ static int expand_tilde(char **pat, char *buf, size_t *pos) return 0; } +static void wrap_closedir(void *p) { __closedir(p); } +static struct dirent *wrap_readdir(void *d) { return __readdir(d); } +static void *wrap_opendir(const char *path) { return __opendir(path); } + int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, int err), glob_t *restrict g) { struct match head = { .next = NULL }, *tail = &head; @@ -224,9 +236,24 @@ int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, i size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0; int error = 0; char buf[PATH_MAX]; + struct dirfn dirfn; if (!errfunc) errfunc = ignore_err; + if (flags & GLOB_ALTDIRFUNC) { + dirfn.closedir = g->gl_closedir; + dirfn.readdir = g->gl_readdir; + dirfn.opendir = g->gl_opendir; + dirfn.lstat = g->gl_lstat; + dirfn.stat = g->gl_stat; + } else { + dirfn.closedir = wrap_closedir; + dirfn.readdir = wrap_readdir; + dirfn.opendir = wrap_opendir; + dirfn.lstat = lstat; + dirfn.stat = stat; + } + if (!(flags & GLOB_APPEND)) { g->gl_offs = offs; g->gl_pathc = 0; @@ -242,7 +269,7 @@ int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, i if ((flags & (GLOB_TILDE | GLOB_TILDE_CHECK)) && *p == '~') error = expand_tilde(&s, buf, &pos); if (!error) - error = do_glob(buf, pos, 0, s, flags, errfunc, &tail); + error = do_glob(buf, pos, 0, s, flags, errfunc, &dirfn, &tail); free(p); } -- 2.22.0
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.