Date: Mon, 2 Jun 2025 09:33:14 GMT From: Bojan =?utf-8?Q?Novkovi=C4=87?= <bnovkov@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 1e0743f54d2d - main - glob: Add blocks support Message-ID: <202506020933.5529XEpk083101@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by bnovkov: URL: https://cgit.FreeBSD.org/src/commit/?id=1e0743f54d2d3624cd4de2167d373aa38597778e commit 1e0743f54d2d3624cd4de2167d373aa38597778e Author: Bojan Novković <bnovkov@FreeBSD.org> AuthorDate: 2025-05-23 13:26:04 +0000 Commit: Bojan Novković <bnovkov@FreeBSD.org> CommitDate: 2025-06-02 09:32:50 +0000 glob: Add blocks support This change introduces the `glob_b` function which takes a block instead of a function pointer. Relnotes: yes Sponsored by: Klara, Inc. Inspired by: https://github.com/apple-oss-distributions/Libc Differential Revision: https://reviews.freebsd.org/D50485 --- include/glob.h | 16 +++++++++-- lib/libc/gen/Makefile.inc | 1 + lib/libc/gen/Symbol.map | 1 + lib/libc/gen/glob.3 | 66 ++++++++++++++++++++++++++++++++++++++------ lib/libc/gen/glob.c | 70 +++++++++++++++++++++++++++++++++++++---------- 5 files changed, 128 insertions(+), 26 deletions(-) diff --git a/include/glob.h b/include/glob.h index dc86cdf99929..cbe99bfef6ed 100644 --- a/include/glob.h +++ b/include/glob.h @@ -50,8 +50,15 @@ typedef struct { size_t gl_offs; /* Reserved at beginning of gl_pathv. */ 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); + /* Copy of error callback parameter to glob. */ + union { + int (*gl_errfunc)(const char *, int); +#ifdef __BLOCKS__ + int (^gl_errblk)(const char *, int); +#else + void *gl_errblk; +#endif + }; /* * Alternate filesystem access methods for glob; replacement @@ -90,6 +97,7 @@ typedef struct { #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 */ +#define _GLOB_ERR_BLOCK 0x08000000 /* (internal) error callback is a block */ /* source compatibility, these are the old names */ #define GLOB_MAXPATH GLOB_LIMIT @@ -99,6 +107,10 @@ typedef struct { __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 index 302fd3a004d1..74b18b44e575 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -172,6 +172,7 @@ SRCS+= \ .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 index 2ddca1f20e00..afc277822787 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -459,6 +459,7 @@ FBSD_1.8 { aio_write2; execvpe; fts_open_b; + glob_b; psiginfo; rtld_get_var; rtld_set_var; diff --git a/lib/libc/gen/glob.3 b/lib/libc/gen/glob.3 index 006e8decb3db..9f15b2edb63a 100644 --- a/lib/libc/gen/glob.3 +++ b/lib/libc/gen/glob.3 @@ -27,11 +27,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 20, 2011 +.Dd June 02, 2025 .Dt GLOB 3 .Os .Sh NAME .Nm glob , +.Nm glob_b, .Nm globfree .Nd generate pathnames matching a pattern .Sh LIBRARY @@ -39,7 +40,9 @@ .Sh SYNOPSIS .In glob.h .Ft int -.Fn glob "const char * restrict pattern" "int flags" "int (*errfunc)(const char *, int)" "glob_t * restrict pglob" +.Fn glob "const char * restrict pattern" "int flags" "int (*errfunc)(const char *epath, int errno)" "glob_t * restrict pglob" +.Ft int +.Fn glob_b "const char * restrict pattern" "int flags" "int (^errblk)(const char *epath, int errno)" "glob_t * restrict pglob" .Ft void .Fn globfree "glob_t *pglob" .Sh DESCRIPTION @@ -272,10 +275,24 @@ is .Pf non- Dv NULL , .Fn glob calls -.Fa \*(lp*errfunc\*(rp Ns ( Fa path , errno ) , +.Fa \*(lp*errfunc\*(rp Ns ( Fa path , errno ) . +This may be unintuitive: a pattern like +.Ql */Makefile +will try to +.Xr stat 2 +.Ql foo/Makefile +even if +.Ql foo +is not a directory, resulting in a +call to +.Fa errfunc . +The error routine can suppress this action by testing for +.Er ENOENT +and +.Er ENOTDIR ; however, the .Dv GLOB_ERR -flag will cause an immediate +flag will still cause an immediate return when this happens. .Pp If @@ -307,16 +324,27 @@ or returns zero, the error is ignored. .Pp The +.Fn glob_b +function is like +.Fn glob +except that the error callback is a block pointer instead of a function +pointer. +.Pp +The .Fn globfree function frees any space associated with .Fa pglob from a previous call(s) to -.Fn glob . +.Fn glob +or +.Fn glob_b . .Sh RETURN VALUES On successful completion, .Fn glob -returns zero. -In addition the fields of +and +.Fn glob_b +return zero. +In addition, the fields of .Fa pglob contain the values described below: .Bl -tag -width GLOB_NOCHECK @@ -324,12 +352,16 @@ contain the values described below: contains the total number of matched pathnames so far. This includes other matches from previous invocations of .Fn glob +or +.Fn glob_b . if .Dv GLOB_APPEND was specified. .It Fa gl_matchc contains the number of matched pathnames in the current invocation of -.Fn glob . +.Fn glob +or +.Fn glob_b . .It Fa gl_flags contains a copy of the .Fa flags @@ -352,6 +384,8 @@ are undefined. .Pp If .Fn glob +or +.Fn glob_b terminates due to an error, it sets errno and returns one of the following non-zero constants, which are defined in the include file @@ -397,6 +431,14 @@ g.gl_pathv[0] = "ls"; g.gl_pathv[1] = "-l"; execvp("ls", g.gl_pathv); .Ed +.Sh CAVEATS +The +.Fn glob +and +.Fn glob_b +functions +will not match filenames that begin with a period +unless this is specifically requested (e.g., by ".*"). .Sh SEE ALSO .Xr sh 1 , .Xr fnmatch 3 , @@ -435,6 +477,10 @@ and .Fn globfree functions first appeared in .Bx 4.4 . +The +.Fn glob_b +function first appeared in +.Fx 15.0 . .Sh BUGS Patterns longer than .Dv MAXPATHLEN @@ -442,7 +488,9 @@ may cause unchecked errors. .Pp The .Fn glob -argument +and +.Fn glob_b +functions may fail and set errno for any of the errors specified for the library routines .Xr stat 2 , diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c index 7a988196549a..1ac919edaa12 100644 --- a/lib/libc/gen/glob.c +++ b/lib/libc/gen/glob.c @@ -88,8 +88,11 @@ #include <unistd.h> #include <wchar.h> +#include "block_abi.h" #include "collate.h" +typedef DECLARE_BLOCK(int, glob_b_block, const char*, int); + /* * glob(3) expansion limits. Stop the expansion if any of these limits * is reached. This caps the runtime in the face of DoS attacks. See @@ -179,9 +182,8 @@ static int err_aborted(glob_t *, int, char *); 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 +194,23 @@ glob(const char * __restrict pattern, int flags, 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,15 +250,45 @@ glob(const char * __restrict pattern, int flags, 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) +{ + int rv; + + pglob->gl_flags = flags & ~(GLOB_MAGCHAR | _GLOB_ERR_BLOCK); + pglob->gl_errfunc = errfunc; + rv = __glob(pattern, pglob); + pglob->gl_errfunc = NULL; + + return (rv); +} + +int +glob_b(const char * __restrict pattern, int flags, + glob_b_block block, glob_t * __restrict pglob) +{ + int rv; + + pglob->gl_flags = flags & ~GLOB_MAGCHAR; + pglob->gl_flags |= _GLOB_ERR_BLOCK; + pglob->gl_errblk = block; + rv = __glob(pattern, pglob); + pglob->gl_errblk = NULL; + + return (rv); +} + static int globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit, - const char *origpat) { + const char *origpat) +{ int rv; size_t oldpathc; @@ -724,7 +754,7 @@ glob3(Char *pathbuf, Char *pathend, Char *pathend_last, 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); @@ -1085,10 +1115,20 @@ err_nomatch(glob_t *pglob, struct glob_limit *limit, const char *origpat) { } 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)) +err_aborted(glob_t *pglob, int err, char *buf) +{ + int rv = 0; + + if ((pglob->gl_flags & _GLOB_ERR_BLOCK) != 0) { + if (pglob->gl_errblk != NULL) + rv = CALL_BLOCK(pglob->gl_errblk, buf, errno); + } else 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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506020933.5529XEpk083101>