Page MenuHomeFreeBSD

D2877.diff
No OneTemporary

D2877.diff

Index: include/err.h
===================================================================
--- include/err.h
+++ include/err.h
@@ -59,6 +59,9 @@
void vwarnx(const char *, __va_list) __printflike(1, 0);
void err_set_file(void *);
void err_set_exit(void (*)(int));
+#ifdef __BLOCKS__
+void err_set_exit_b(void (^)(int));
+#endif /* __BLOCKS__ */
__END_DECLS
#endif /* !_ERR_H_ */
Index: include/fts.h
===================================================================
--- include/fts.h
+++ include/fts.h
@@ -44,8 +44,12 @@
int fts_rfd; /* fd for root */
__size_t fts_pathlen; /* sizeof(path) */
__size_t fts_nitems; /* elements in the sort array */
- int (*fts_compar) /* compare function */
- (const struct _ftsent * const *, const struct _ftsent * const *);
+ union {
+ int (*fts_compar) /* compare function */
+ (const struct _ftsent * const *,
+ const struct _ftsent * const *);
+ void *fts_compar_b; /* compare block */
+ };
#define FTS_COMFOLLOW 0x001 /* follow command line symlinks */
#define FTS_LOGICAL 0x002 /* logical walk */
@@ -59,6 +63,7 @@
#define FTS_NAMEONLY 0x100 /* (private) child names only */
#define FTS_STOP 0x200 /* (private) unrecoverable error */
+#define FTS_COMPAR_B 0x400 /* (private) use block compare */
int fts_options; /* fts_open options, global flags */
void *fts_clientptr; /* thunk for sort function */
} FTS;
@@ -128,6 +133,10 @@
#define fts_get_stream(ftsent) ((ftsent)->fts_fts)
FTS *fts_open(char * const *, int,
int (*)(const FTSENT * const *, const FTSENT * const *));
+#ifdef __BLOCKS__
+FTS *fts_open_b(char * const *, int,
+ int (^)(const FTSENT * const *, const FTSENT * const *));
+#endif /* __BLOCKS__ */
FTSENT *fts_read(FTS *);
int fts_set(FTS *, FTSENT *, int);
void fts_set_clientptr(FTS *, void *);
Index: include/glob.h
===================================================================
--- include/glob.h
+++ include/glob.h
@@ -51,8 +51,12 @@
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 errfunc/errblock parameter to
+ glob/glob_b.*/
+ union {
+ int (*gl_errfunc)(const char *, int);
+ void *gl_errblk;
+ };
/*
* Alternate filesystem access methods for glob; replacement
@@ -92,6 +96,8 @@
#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
#define GLOB_LIMIT 0x1000 /* limit number of returned paths */
+#define _GLOB_ERRBLK 0x80000000 /* (private) err callback is block */
+
/* source compatibility, these are the old names */
#define GLOB_MAXPATH GLOB_LIMIT
#define GLOB_ABEND GLOB_ABORTED
@@ -100,6 +106,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 /* __BLOCKS__ */
void globfree(glob_t *);
__END_DECLS
Index: lib/libc/gen/Makefile.inc
===================================================================
--- lib/libc/gen/Makefile.inc
+++ lib/libc/gen/Makefile.inc
@@ -319,6 +319,7 @@
dlopen.3 dlfunc.3 \
dlopen.3 dlsym.3
MLINKS+=err.3 err_set_exit.3 \
+ err.3 err_set_exit_b.3 \
err.3 err_set_file.3 \
err.3 errc.3 \
err.3 errx.3 \
@@ -349,6 +350,7 @@
MLINKS+=fts.3 fts_children.3 \
fts.3 fts_close.3 \
fts.3 fts_open.3 \
+ fts.3 fts_open_b.3 \
fts.3 fts_read.3 \
fts.3 fts_set.3 \
fts.3 fts_set_clientptr.3 \
@@ -413,7 +415,8 @@
getutxent.3 setutxdb.3 \
getutxent.3 setutxent.3 \
getutxent.3 utmpx.3
-MLINKS+=glob.3 globfree.3
+MLINKS+=glob.3 globfree.3 \
+ glob.3 glob_b.3
MLINKS+=isgreater.3 isgreaterequal.3 \
isgreater.3 isless.3 \
isgreater.3 islessequal.3 \
Index: lib/libc/gen/Symbol.map
===================================================================
--- lib/libc/gen/Symbol.map
+++ lib/libc/gen/Symbol.map
@@ -410,6 +410,9 @@
};
FBSD_1.4 {
+ err_set_exit_b;
+ fts_open_b;
+ glob_b;
scandir_b;
};
Index: lib/libc/gen/err.3
===================================================================
--- lib/libc/gen/err.3
+++ lib/libc/gen/err.3
@@ -28,7 +28,7 @@
.\" From: @(#)err.3 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
-.Dd March 29, 2012
+.Dd June 25, 2015
.Dt ERR 3
.Os
.Sh NAME
@@ -45,6 +45,7 @@
.Nm warnx ,
.Nm vwarnx ,
.Nm err_set_exit ,
+.Nm err_set_exit_b ,
.Nm err_set_file
.Nd formatted error messages
.Sh LIBRARY
@@ -54,8 +55,10 @@
.Ft void
.Fn err "int eval" "const char *fmt" "..."
.Ft void
-.Fn err_set_exit "void (*exitf)(int)"
+.Fn err_set_exit "void (*exitfunc)(int)"
.Ft void
+.Fn err_set_exit_b "void (^exitblock)(int)"
+.Ft void
.Fn err_set_file "void *vfp"
.Ft void
.Fn errc "int eval" "int code" "const char *fmt" "..."
@@ -162,10 +165,23 @@
.Fn err_set_exit
function can be used to specify a function which is called before
.Xr exit 3
-to perform any necessary cleanup; passing a null function pointer for
-.Va exitf
+to perform any necessary cleanup.
+Passing a null function pointer for
+.Va exitfunc
resets the hook to do nothing.
The
+.Fn err_set_exit_b
+function is like
+.Fn err_set_exit ,
+except it takes the block pointer,
+.Va exitblock ,
+instead of a function pointer.
+Note that the
+.Fn Block_copy
+function is used by
+.Fn err_set_exit_b
+to make a copy in case the block is freed or goes out of scope.
+The
.Fn err_set_file
function sets the output stream used by the other functions.
Its
@@ -243,3 +259,8 @@
.Fn warnc
functions first appeared in
.Fx 3.0 .
+The
+.Fn err_set_exit_b
+function first appeared in Mac OS X. This implementation was
+created by Stacey Son for
+.Fx 11.0 .
Index: lib/libc/gen/err.c
===================================================================
--- lib/libc/gen/err.c
+++ lib/libc/gen/err.c
@@ -40,6 +40,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "block_abi.h"
#include "un-namespace.h"
#include "libc_private.h"
@@ -46,6 +47,7 @@
static FILE *err_file; /* file to use for error output */
static void (*err_exit)(int);
+typedef DECLARE_BLOCK(void, err_exit_block_t, int);
/*
* This is declared to take a `void *' so that the caller is not required
@@ -67,6 +69,17 @@
err_exit = ef;
}
+/*
+ * Register a block to be executed at error exit.
+ */
+void
+err_set_exit_b(err_exit_block_t block)
+{
+
+ if (_Block_copy != 0)
+ err_exit = (void(*)(int))GET_BLOCK_FUNCTION(_Block_copy(block));
+}
+
__weak_reference(_err, err);
void
Index: lib/libc/gen/fts.3
===================================================================
--- lib/libc/gen/fts.3
+++ lib/libc/gen/fts.3
@@ -28,7 +28,7 @@
.\" @(#)fts.3 8.5 (Berkeley) 4/16/94
.\" $FreeBSD$
.\"
-.Dd January 12, 2014
+.Dd May 5, 2014
.Dt FTS 3
.Os
.Sh NAME
@@ -40,6 +40,8 @@
.In fts.h
.Ft FTS *
.Fn fts_open "char * const *path_argv" "int options" "int (*compar)(const FTSENT * const *, const FTSENT * const *)"
+.Ft FTS *
+.Fn fts_open_b "char * const *path_argv" "int options" "int (^compar)(const FTSENT * const *, const FTSENT * const *)"
.Ft FTSENT *
.Fn fts_read "FTS *ftsp"
.Ft FTSENT *
@@ -62,7 +64,9 @@
file hierarchies.
A simple overview is that the
.Fn fts_open
-function returns a
+and
+.Fn fts_open_b
+functions return a
.Dq handle
on a file hierarchy, which is then supplied to
the other
@@ -189,6 +193,8 @@
.Ql ..\&
which was not specified as a file name to
.Fn fts_open
+or
+.Fn fts_open_b
(see
.Dv FTS_SEEDOT ) .
.It Dv FTS_DP
@@ -237,6 +243,8 @@
The path for the file relative to the root of the traversal.
This path contains the path specified to
.Fn fts_open
+or
+.Fn fts_open_b
as a prefix.
.It Fa fts_pathlen
The length of the string referenced by
@@ -521,6 +529,14 @@
.Fa path_argv
for the root paths, and in the order listed in the directory for
everything else.
+.Sh FTS_OPEN_B
+.Fn fts_open_b
+is a block-based version of
+.Fn fts_open
+where
+.Fa compar
+is a block pointer that is passed to
+.Xr qsort_b 3 .
.Sh FTS_READ
The
.Fn fts_read
@@ -775,7 +791,8 @@
.Xr chdir 2 ,
.Xr stat 2 ,
.Xr ftw 3 ,
-.Xr qsort 3
+.Xr qsort 3 ,
+.Xr qsort_b 3
.Sh HISTORY
The
.Nm
@@ -791,10 +808,17 @@
principally to provide for alternative interfaces to the
.Nm
functionality using different data structures.
+The
+.Fn fts_open_b
+function first appeared in Mac OS X.
+This implementation was created by Stacey Son for
+.Fx 11.0 .
.Sh BUGS
The
.Fn fts_open
-function will automatically set the
+and
+.Fn fts_open_b
+functions will automatically set the
.Dv FTS_NOCHDIR
option if the
.Dv FTS_LOGICAL
Index: lib/libc/gen/fts.c
===================================================================
--- lib/libc/gen/fts.c
+++ lib/libc/gen/fts.c
@@ -50,10 +50,15 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include "block_abi.h"
#include "un-namespace.h"
#include "gen-private.h"
+/* fts_block_t */
+typedef DECLARE_BLOCK(int, fts_block_t, const FTSENT * const *,
+ const FTSENT * const *);
+
static FTSENT *fts_alloc(FTS *, char *, size_t);
static FTSENT *fts_build(FTS *, int);
static void fts_lfree(FTSENT *);
@@ -109,37 +114,16 @@
0
};
-FTS *
-fts_open(argv, options, compar)
+static FTS *
+_fts_open_common(argv, priv)
char * const *argv;
- int options;
- int (*compar)(const FTSENT * const *, const FTSENT * const *);
+ struct _fts_private *priv;
{
- struct _fts_private *priv;
- FTS *sp;
+ FTS *sp = &priv->ftsp_fts;
FTSENT *p, *root;
FTSENT *parent, *tmp;
size_t len, nitems;
- /* Options check. */
- if (options & ~FTS_OPTIONMASK) {
- errno = EINVAL;
- return (NULL);
- }
-
- /* fts_open() requires at least one path */
- if (*argv == NULL) {
- errno = EINVAL;
- return (NULL);
- }
-
- /* Allocate/initialize the stream. */
- if ((priv = calloc(1, sizeof(*priv))) == NULL)
- return (NULL);
- sp = &priv->ftsp_fts;
- sp->fts_compar = compar;
- sp->fts_options = options;
-
/* Shush, GCC. */
tmp = NULL;
@@ -177,7 +161,7 @@
* If comparison routine supplied, traverse in sorted
* order; otherwise traverse in the order specified.
*/
- if (compar) {
+ if (sp->fts_compar) {
p->fts_link = root;
root = p;
} else {
@@ -190,7 +174,7 @@
}
}
}
- if (compar && nitems > 1)
+ if (sp->fts_compar && nitems > 1)
root = fts_sort(sp, root, nitems);
/*
@@ -223,6 +207,66 @@
return (NULL);
}
+static int
+_fts_open_argcheck(char * const *argv, int options)
+{
+
+ /*
+ * Check for illegal options and for at least one path.
+ */
+ if (options & ~FTS_OPTIONMASK || *argv == NULL)
+ return (EINVAL);
+
+ return (0);
+}
+
+FTS *
+fts_open(char * const *argv, int options, int (*compar)(const FTSENT * const *,
+ const FTSENT * const *))
+{
+ FTS *sp;
+ struct _fts_private *priv;
+
+ /* Check arguments. */
+ if ((errno = _fts_open_argcheck(argv, options)) != 0)
+ return (NULL);
+
+ /* Allocate/initialize the stream. */
+ if ((priv = calloc(1, sizeof(*priv))) == NULL)
+ return (NULL);
+ sp = &priv->ftsp_fts;
+ sp->fts_compar = compar;
+ sp->fts_options = options;
+
+ return (_fts_open_common(argv, priv));
+}
+
+FTS *
+fts_open_b(char * const *argv, int options, fts_block_t compar)
+{
+ FTS *sp;
+ struct _fts_private *priv;
+
+ /* Check arguments. */
+ if ((errno = _fts_open_argcheck(argv, options)) != 0)
+ return (NULL);
+
+ /* Check to make sure we have the block runtime. */
+ if (_Block_copy == 0) {
+ errno = ENOSYS;
+ return (NULL);
+ }
+
+ /* Allocate/initialize the stream. */
+ if ((priv = calloc(1, sizeof(*priv))) == NULL)
+ return (NULL);
+ sp = &priv->ftsp_fts;
+ sp->fts_compar_b = _Block_copy(compar);
+ sp->fts_options = options | FTS_COMPAR_B;
+
+ return (_fts_open_common(argv, priv));
+}
+
static void
fts_load(FTS *sp, FTSENT *p)
{
@@ -274,6 +318,11 @@
free(sp->fts_array);
free(sp->fts_path);
+ /* Free block pointer, if any. */
+ if (ISSET(FTS_COMPAR_B) && sp->fts_compar_b != NULL &&
+ _Block_release != 0)
+ _Block_release(sp->fts_compar_b);
+
/* Return to original directory, save errno if necessary. */
if (!ISSET(FTS_NOCHDIR)) {
saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
@@ -973,6 +1022,17 @@
return (*parent->fts_compar)(a, b);
}
+static int
+fts_compar_b(void *thunk, const void *a, const void *b)
+{
+ FTS *sp = (FTS *)thunk;
+ int (*funcp)(const void *, const void *);
+
+ funcp = (int (*)(const void *, const void *))
+ GET_BLOCK_FUNCTION(sp->fts_compar_b);
+ return (*funcp)(a, b);
+}
+
static FTSENT *
fts_sort(FTS *sp, FTSENT *head, size_t nitems)
{
@@ -995,7 +1055,11 @@
}
for (ap = sp->fts_array, p = head; p; p = p->fts_link)
*ap++ = p;
- qsort(sp->fts_array, nitems, sizeof(FTSENT *), fts_compar);
+ if (ISSET(FTS_COMPAR_B))
+ qsort_r(sp->fts_array, nitems, sizeof(FTSENT *),
+ sp->fts_compar_b, fts_compar_b);
+ else
+ qsort(sp->fts_array, nitems, sizeof(FTSENT *), fts_compar);
for (head = *(ap = sp->fts_array); --nitems; ++ap)
ap[0]->fts_link = ap[1];
ap[0]->fts_link = NULL;
Index: lib/libc/gen/glob.3
===================================================================
--- lib/libc/gen/glob.3
+++ lib/libc/gen/glob.3
@@ -30,11 +30,12 @@
.\" @(#)glob.3 8.3 (Berkeley) 4/16/94
.\" $FreeBSD$
.\"
-.Dd December 20, 2011
+.Dd May 5, 2014
.Dt GLOB 3
.Os
.Sh NAME
.Nm glob ,
+.Nm glob_b ,
.Nm globfree
.Nd generate pathnames matching a pattern
.Sh LIBRARY
@@ -43,6 +44,8 @@
.In glob.h
.Ft int
.Fn glob "const char * restrict pattern" "int flags" "int (*errfunc)(const char *, int)" "glob_t * restrict pglob"
+.Ft int
+.Fn glob_b "const char * restrict pattern" "int flags" "int (^errblock)(const char *, int)" "glob_t * restrict pglob"
.Ft void
.Fn globfree "glob_t *pglob"
.Sh DESCRIPTION
@@ -72,7 +75,7 @@
is a pointer to a pathname pattern to be expanded.
The
.Fn glob
-argument
+function
matches all accessible pathnames against the pattern and creates
a list of the pathnames that match.
In order to have access to a pathname,
@@ -88,7 +91,7 @@
.Pp
The
.Fn glob
-argument
+function
stores the number of matched pathnames into the
.Fa gl_pathc
field, and a pointer to a list of pointers to pathnames into the
@@ -323,6 +326,12 @@
.Fa errfunc
returns zero, the error is ignored.
.Pp
+.Fn glob_b
+is a block-based version of
+.Fn glob .
+where the error callback is the block pointer,
+.Fa errblock .
+.Pp
The
.Fn globfree
function frees any space associated with
@@ -332,7 +341,9 @@
.Sh RETURN VALUES
On successful completion,
.Fn glob
-returns zero.
+and
+.Fn glob_b
+return zero.
In addition the fields of
.Fa pglob
contain the values described below:
@@ -341,12 +352,16 @@
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
@@ -369,6 +384,8 @@
.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
@@ -452,6 +469,11 @@
.Fn globfree
functions first appeared in
.Bx 4.4 .
+The
+.Fn glob_b
+function first appeared in Mac OS X.
+This implementation was created by Stacey Son for
+.Fx 11.0 .
.Sh BUGS
Patterns longer than
.Dv MAXPATHLEN
@@ -459,7 +481,9 @@
.Pp
The
.Fn glob
-argument
+or
+.Fn glob_b
+function
may fail and set errno for any of the errors specified for the
library routines
.Xr stat 2 ,
Index: lib/libc/gen/glob.c
===================================================================
--- lib/libc/gen/glob.c
+++ lib/libc/gen/glob.c
@@ -92,8 +92,12 @@
#include <unistd.h>
#include <wchar.h>
+#include "block_abi.h"
#include "collate.h"
+/* errblock_t */
+typedef DECLARE_BLOCK(int, errblock_t, 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
@@ -189,9 +193,9 @@
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_common(const char * __restrict pattern, int flags,
+ glob_t * __restrict pglob)
{
struct glob_limit limit = { 0, 0, 0, 0, 0 };
const char *patnext;
@@ -212,8 +216,6 @@
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;
@@ -258,6 +260,28 @@
return (glob0(patbuf, pglob, &limit));
}
+int
+glob(const char * __restrict pattern, int flags,
+ int (*errfunc)(const char *, int), glob_t * __restrict pglob)
+{
+
+ pglob->gl_flags = flags & ~(GLOB_MAGCHAR | _GLOB_ERRBLK);
+ pglob->gl_errfunc = errfunc;
+ return (_glob_common(pattern, flags, pglob));
+}
+
+int
+glob_b(const char * __restrict pattern, int flags, errblock_t errblock,
+ glob_t * __restrict pglob)
+{
+
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_flags |= _GLOB_ERRBLK;
+ pglob->gl_errblk = (void *)errblock;
+
+ return (_glob_common(pattern, flags, pglob));
+}
+
/*
* Expand recursively a glob {} pattern. When there is no more expansion
* invoke the standard globbing routine to glob the rest of the magic
@@ -649,6 +673,7 @@
DIR *dirp;
int err;
char buf[MAXPATHLEN];
+ int (*errfunc)(const char *, int);
/*
* The readdirfunc declaration can't be prototyped, because it is
@@ -668,7 +693,13 @@
if (pglob->gl_errfunc) {
if (g_Ctoc(pathbuf, buf, sizeof(buf)))
return (GLOB_ABORTED);
- if (pglob->gl_errfunc(buf, errno) ||
+printf("glob3: %p %d\n", buf, errno);
+ if (pglob->gl_flags & _GLOB_ERRBLK)
+ errfunc = (int (*)(const char *, int))
+ GET_BLOCK_FUNCTION(pglob->gl_errblk);
+ else
+ errfunc = pglob->gl_errfunc;
+ if ((*errfunc)(buf, errno) ||
pglob->gl_flags & GLOB_ERR)
return (GLOB_ABORTED);
}
Index: lib/libc/include/block_abi.h
===================================================================
--- lib/libc/include/block_abi.h
+++ lib/libc/include/block_abi.h
@@ -26,6 +26,8 @@
* $FreeBSD$
*/
+#include <sys/cdefs.h>
+
#ifdef __BLOCKS__
/**
* Declares a block variable. This macro is defined in the trivial way for
@@ -61,3 +63,9 @@
int reserved;\
void (*invoke)(void *, ...);\
}*)(void*)x)->invoke)
+
+/*
+ * _Block_copy() and _Block_release() are provided by libBlocksRuntime.
+ */
+__weak_symbol void *_Block_copy(void *);
+__weak_symbol void _Block_release(void *);

File Metadata

Mime Type
text/plain
Expires
Sat, May 23, 12:52 PM (14 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33446794
Default Alt Text
D2877.diff (18 KB)

Event Timeline