diff --git a/include/glob.h b/include/glob.h --- a/include/glob.h +++ b/include/glob.h @@ -51,7 +51,14 @@ int gl_flags; /* Copy of flags parameter to glob. */ char **gl_pathv; /* List of paths matching pattern. */ /* Copy of errfunc parameter to glob. */ - int (*gl_errfunc)(const char *, int); +#ifdef __BLOCKS__ + union { +#endif /* __BLOCKS__ */ + int (*gl_errfunc)(const char *, int); +#ifdef __BLOCKS__ + int (^gl_errblk)(const char *, int); + }; +#endif /* __BLOCKS__ */ /* * Alternate filesystem access methods for glob; replacement @@ -90,6 +97,9 @@ #define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ #define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ #define GLOB_LIMIT 0x1000 /* limit number of returned paths */ +#ifdef __BLOCKS__ +#define _GLOB_ERR_BLOCK 0x80000000 /* (internal) error callback is a block */ +#endif /* __BLOCKS__ */ /* source compatibility, these are the old names */ #define GLOB_MAXPATH GLOB_LIMIT @@ -99,6 +109,10 @@ __BEGIN_DECLS int glob(const char * __restrict, int, int (*)(const char *, int), glob_t * __restrict); +#ifdef __BLOCKS__ +int glob_b(const char * __restrict, int, + int (^)(const char *, int), glob_t * __restrict); +#endif void globfree(glob_t *); __END_DECLS diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -170,6 +170,7 @@ .if ${COMPILER_FEATURES:Mblocks} CFLAGS.fts.c= -fblocks +CFLAGS.glob.c= -fblocks .endif CFLAGS.arc4random.c= -I${SRCTOP}/sys -I${SRCTOP}/sys/crypto/chacha20 diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -459,6 +459,7 @@ aio_write2; execvpe; fts_open_b; + glob_b; psiginfo; rtld_get_var; rtld_set_var; diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c --- a/lib/libc/gen/glob.c +++ b/lib/libc/gen/glob.c @@ -179,9 +179,8 @@ static void qprintf(const char *, Char *); #endif -int -glob(const char * __restrict pattern, int flags, - int (*errfunc)(const char *, int), glob_t * __restrict pglob) +static int +__glob(const char *pattern, glob_t *pglob) { struct glob_limit limit = { 0, 0, 0, 0, 0 }; const char *patnext; @@ -192,25 +191,23 @@ int too_long; patnext = pattern; - if (!(flags & GLOB_APPEND)) { + if (!(pglob->gl_flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; - if (!(flags & GLOB_DOOFFS)) + if (!(pglob->gl_flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } - if (flags & GLOB_LIMIT) { + if (pglob->gl_flags & GLOB_LIMIT) { limit.l_path_lim = pglob->gl_matchc; if (limit.l_path_lim == 0) limit.l_path_lim = GLOB_LIMIT_PATH; } - pglob->gl_flags = flags & ~GLOB_MAGCHAR; - pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; bufnext = patbuf; bufend = bufnext + MAXPATHLEN - 1; too_long = 1; - if (flags & GLOB_NOESCAPE) { + if (pglob->gl_flags & GLOB_NOESCAPE) { memset(&mbs, 0, sizeof(mbs)); while (bufnext <= bufend) { clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); @@ -250,12 +247,37 @@ return (err_nomatch(pglob, &limit, pattern)); *bufnext = EOS; - if (flags & GLOB_BRACE) + if (pglob->gl_flags & GLOB_BRACE) return (globexp0(patbuf, pglob, &limit, pattern)); else return (glob0(patbuf, pglob, &limit, pattern)); } +int +glob(const char * __restrict pattern, int flags, + int (*errfunc)(const char *, int), glob_t * __restrict pglob) +{ +#ifdef __BLOCKS__ + pglob->gl_flags = flags & ~(GLOB_MAGCHAR | _GLOB_ERR_BLOCK); +#else /* !__BLOCKS__ */ + pglob->gl_flags = flags & ~GLOB_MAGCHAR; +#endif /* __BLOCKS__ */ + pglob->gl_errfunc = errfunc; + return (__glob(pattern, pglob)); +} + +#ifdef __BLOCKS__ +int +glob_b(const char * __restrict pattern, int flags, + int (^errblk)(const char *, int), glob_t * __restrict pglob) +{ + pglob->gl_flags = flags & ~GLOB_MAGCHAR; + pglob->gl_flags |= _GLOB_ERR_BLOCK; + pglob->gl_errblk = errblk; + return (__glob(pattern, pglob)); +} +#endif /* __BLOCKS__ */ + static int globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, const char *origpat) { @@ -724,7 +746,7 @@ return (GLOB_NOSPACE); } *pathend = EOS; - if (pglob->gl_errfunc != NULL && + if ((pglob->gl_errfunc != NULL || pglob->gl_errblk != NULL) && g_Ctoc(pathbuf, buf, sizeof(buf))) { errno = E2BIG; return (GLOB_NOSPACE); @@ -1086,9 +1108,22 @@ static int err_aborted(glob_t *pglob, int err, char *buf) { - if ((pglob->gl_errfunc != NULL && pglob->gl_errfunc(buf, err)) || - (pglob->gl_flags & GLOB_ERR)) + int rv; + + rv = 0; +#ifdef __BLOCKS__ + if ((pglob->gl_flags & _GLOB_ERR_BLOCK) != 0 && + pglob->gl_errblk != NULL) { + rv = pglob->gl_errblk(buf, errno); + } else +#endif /* __BLOCKS__ */ + if (pglob->gl_errfunc != NULL) { + rv = pglob->gl_errfunc(buf, errno); + } + /* GLOB_ERR is allowed to override the error callback function. */ + if (rv != 0 || pglob->gl_flags & GLOB_ERR) { return (GLOB_ABORTED); + } return (0); }