From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/14494 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Ismael Luceno Newsgroups: gmane.linux.lib.musl.general Subject: [PATCH v2] glob: implement GLOB_ALTDIRFUNC et al Date: Thu, 1 Aug 2019 20:01:13 +0200 Message-ID: <20190801180113.24330-2-ismael@iodev.co.uk> References: <20190801180113.24330-1-ismael@iodev.co.uk> Reply-To: musl@lists.openwall.com Mime-Version: 1.0 Content-Transfer-Encoding: 8bit Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="253377"; mail-complaints-to="usenet@blaine.gmane.org" Cc: Ismael Luceno To: musl@lists.openwall.com Original-X-From: musl-return-14510-gllmg-musl=m.gmane.org@lists.openwall.com Thu Aug 01 20:01:40 2019 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by blaine.gmane.org with smtp (Exim 4.89) (envelope-from ) id 1htFOW-0013oK-9o for gllmg-musl@m.gmane.org; Thu, 01 Aug 2019 20:01:40 +0200 Original-Received: (qmail 21837 invoked by uid 550); 1 Aug 2019 18:01:36 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Original-Received: (qmail 21730 invoked from network); 1 Aug 2019 18:01:35 -0000 X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190801180113.24330-1-ismael@iodev.co.uk> Xref: news.gmane.org gmane.linux.lib.musl.general:14494 Archived-At: Signed-off-by: Ismael Luceno --- 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 #include #include -#include #include #include #include @@ -11,6 +11,14 @@ #include #include +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