diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2014-08-31 02:21:19 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2014-08-31 02:21:19 +0000 |
commit | 13ce210035fe567fec6650d96844a253e5447c54 (patch) | |
tree | 280df60d17551f05f4b39ff8aeff8f325f88f436 /lib/libc/stdio | |
parent | b69e25c758b3865a13793b76dfdbaba108817277 (diff) |
Add additional userland interfaces for setting close-on-exec on fds
when creating them: mkostemp(), mkostemps(), the 'e' mode letter for
fopen(), freopen(), fdopen(), and popen(). The close-on-exec flag will
be cleared by the action created by posix_spawn_file_actions_adddup2().
Also, add support for the C11 'x' mode letter for fopen() and freopen(),
setting O_EXCL when possibly creating files.
Note: this requires kernel support for pipe2() and dup3()!
ok millert@
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r-- | lib/libc/stdio/Makefile.inc | 4 | ||||
-rw-r--r-- | lib/libc/stdio/fdopen.c | 10 | ||||
-rw-r--r-- | lib/libc/stdio/flags.c | 35 | ||||
-rw-r--r-- | lib/libc/stdio/fopen.3 | 59 | ||||
-rw-r--r-- | lib/libc/stdio/freopen.c | 4 | ||||
-rw-r--r-- | lib/libc/stdio/mktemp.3 | 148 | ||||
-rw-r--r-- | lib/libc/stdio/mktemp.c | 34 |
7 files changed, 231 insertions, 63 deletions
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc index cc18c817475..3d19193e315 100644 --- a/lib/libc/stdio/Makefile.inc +++ b/lib/libc/stdio/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.25 2014/03/23 23:15:58 tedu Exp $ +# $OpenBSD: Makefile.inc,v 1.26 2014/08/31 02:21:18 guenther Exp $ # stdio sources .PATH: ${LIBCSRCDIR}/stdio @@ -40,6 +40,8 @@ MLINKS+=getdelim.3 getline.3 MLINKS+=mktemp.3 mkstemp.3 MLINKS+=mktemp.3 mkdtemp.3 MLINKS+=mktemp.3 mkstemps.3 +MLINKS+=mktemp.3 mkostemp.3 +MLINKS+=mktemp.3 mkostemps.3 MLINKS+=open_memstream.3 open_wmemstream.3 MLINKS+=printf.3 fprintf.3 printf.3 snprintf.3 printf.3 sprintf.3 \ printf.3 vfprintf.3 printf.3 vprintf.3 printf.3 vsnprintf.3 \ diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c index 3e47f2c7426..1c0c8132fd2 100644 --- a/lib/libc/stdio/fdopen.c +++ b/lib/libc/stdio/fdopen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fdopen.c,v 1.6 2008/04/21 12:28:35 otto Exp $ */ +/* $OpenBSD: fdopen.c,v 1.7 2014/08/31 02:21:18 guenther Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -66,6 +66,7 @@ fdopen(int fd, const char *mode) if ((fp = __sfp()) == NULL) return (NULL); fp->_flags = flags; + /* * If opened for appending, but underlying descriptor does not have * O_APPEND bit set, assert __SAPP so that __swrite() will lseek to @@ -73,6 +74,13 @@ fdopen(int fd, const char *mode) */ if ((oflags & O_APPEND) && !(fdflags & O_APPEND)) fp->_flags |= __SAPP; + + /* + * If close-on-exec was requested, then turn it on if not already + */ + if ((oflags & O_CLOEXEC) && !((tmp = fcntl(fd, F_GETFD)) & FD_CLOEXEC)) + fcntl(fd, F_SETFD, tmp | FD_CLOEXEC); + fp->_file = fd; fp->_cookie = fp; fp->_read = __sread; diff --git a/lib/libc/stdio/flags.c b/lib/libc/stdio/flags.c index 8cd1ce279d0..d6df6daab88 100644 --- a/lib/libc/stdio/flags.c +++ b/lib/libc/stdio/flags.c @@ -1,4 +1,4 @@ -/* $OpenBSD: flags.c,v 1.7 2013/11/12 07:04:35 deraadt Exp $ */ +/* $OpenBSD: flags.c,v 1.8 2014/08/31 02:21:18 guenther Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -72,11 +72,34 @@ __sflags(const char *mode, int *optr) return (0); } - /* [rwa]\+ or [rwa]b\+ means read and write */ - if (*mode == '+' || (*mode == 'b' && mode[1] == '+')) { - ret = __SRW; - m = O_RDWR; - } + while (*mode != '\0') + switch (*mode++) { + case 'b': + break; + case '+': + ret = __SRW; + m = O_RDWR; + break; + case 'e': + o |= O_CLOEXEC; + break; + case 'x': + if (o & O_CREAT) + o |= O_EXCL; + break; + default: + /* + * Lots of software passes other extension mode + * letters, like Window's 't' + */ +#if 0 + errno = EINVAL; + return (0); +#else + break; +#endif + } + *optr = m | o; return (ret); } diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3 index fda35fbb772..63451c35c49 100644 --- a/lib/libc/stdio/fopen.3 +++ b/lib/libc/stdio/fopen.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: fopen.3,v 1.27 2013/06/05 03:39:23 tedu Exp $ +.\" $OpenBSD: fopen.3,v 1.28 2014/08/31 02:21:18 guenther Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -31,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: June 5 2013 $ +.Dd $Mdocdate: August 31 2014 $ .Dt FOPEN 3 .Os .Sh NAME @@ -59,33 +59,59 @@ The argument points to a string beginning with one of the following sequences (additional characters may follow these sequences): .Bl -tag -width indent -.It Dq Li r +.It Do Li r Dc or Do Li rb Dc Open file for reading. -.It Dq Li r+ +.It Do Li r+ Dc or Do Li rb+ Dc or Do Li r+b Dc Open for reading and writing. -.It Dq Li w +.It Do Li w Dc or Do Li wb Dc Open for writing. The file is created if it does not exist, otherwise it is truncated. -.It Dq Li w+ +.It Do Li w+ Dc or Do Li wb+ Dc or Do Li w+b Dc Open for reading and writing. The file is created if it does not exist, otherwise it is truncated. -.It Dq Li a +.It Do Li a Dc or Do Li ab Dc Open for writing. The file is created if it does not exist. -.It Dq Li a+ +.It Do Li a+ Dc or Do Li ab+ Dc or Do Li a+b Dc Open for reading and writing. The file is created if it does not exist. .El .Pp -The +The letter ``b'' in the .Fa mode -string can also include the letter ``b'' either as the last character or -as a character between the characters in any of the two-character strings -described above. -This is strictly for compatibility with +strings above is strictly for compatibility with .St -ansiC and has no effect; the ``b'' is ignored. .Pp +After any of the above prefixes, the +.Fa mode +string can also include zero or more of the following: +.Bl -tag -width indent +.It Dq Li e +The close-on-exec flag is set on the underlying file descriptor of the new +.Vt FILE . +.It Dq Li x +If the +.Fa mode +string starts with +.Dq w +or +.Dq a +then the function shall fail if file +.Fa path +already exist, as if the +.Dv O_EXCL +flag was passed to the +.Xr open +function. +It has no effect if used with +.Fn fdopen +or the +.Fa mode +string begins with +.Dq r . +.El +.Pp The .Fn fopen and @@ -242,6 +268,13 @@ functions first appeared in .Pp Opening a file for both reading and writing has been possible since .Bx 2 . +.Pp +Support for the +.Dq e +and +.Dq x +mode letters appeared in +.Ox 5.7 . .Sh AUTHORS .An Dennis Ritchie originally implemented diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c index 3158fb174dd..82717b1e26c 100644 --- a/lib/libc/stdio/freopen.c +++ b/lib/libc/stdio/freopen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: freopen.c,v 1.13 2009/11/09 00:18:27 kurt Exp $ */ +/* $OpenBSD: freopen.c,v 1.14 2014/08/31 02:21:18 guenther Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -134,7 +134,7 @@ freopen(const char *file, const char *mode, FILE *fp) * assume stderr is always fd STDERR_FILENO, even if being freopen'd. */ if (wantfd >= 0 && f != wantfd) { - if (dup2(f, wantfd) >= 0) { + if (dup3(f, wantfd, oflags & O_CLOEXEC) >= 0) { (void) close(f); f = wantfd; } diff --git a/lib/libc/stdio/mktemp.3 b/lib/libc/stdio/mktemp.3 index 70559fb8185..38ef80008ef 100644 --- a/lib/libc/stdio/mktemp.3 +++ b/lib/libc/stdio/mktemp.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: mktemp.3,v 1.51 2013/06/05 03:39:23 tedu Exp $ +.\" $OpenBSD: mktemp.3,v 1.52 2014/08/31 02:21:18 guenther Exp $ .\" .\" Copyright (c) 1989, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -27,13 +27,15 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: June 5 2013 $ +.Dd $Mdocdate: August 31 2014 $ .Dt MKTEMP 3 .Os .Sh NAME .Nm mktemp , .Nm mkstemp , +.Nm mkostemp , .Nm mkstemps , +.Nm mkostemps , .Nm mkdtemp .Nd make temporary file name (unique) .Sh SYNOPSIS @@ -46,21 +48,34 @@ .Fn mkstemps "char *template" "int suffixlen" .Ft char * .Fn mkdtemp "char *template" +.In stdlib.h +.In fcntl.h +.Ft int +.Fn mkostemp "char *template" "int flags" +.Ft int +.Fn mkostemps "char *template" "int suffixlen" "int oflags" .Sh DESCRIPTION The .Fn mktemp family of functions take the given file name template and overwrite a portion of it to create a new file name. This file name is unique and suitable for use by the application. -The template may be any file name with at least six trailing Xs, +The template may be any file name with at least six trailing +.Em X Ns s , for example .Pa /tmp/temp.XXXXXXXX . -The trailing Xs are replaced with a unique digit and letter combination. +The trailing +.Em X Ns s +are replaced with a unique digit and letter combination. The number of unique file names that can be returned -depends on the number of Xs provided; +depends on the number of +.Em X Ns s +provided; .Fn mktemp will try at least 2 ** 31 combinations before giving up. -At least six Xs must be used, though 10 is much better. +At least six +.Em X Ns s +must be used, though 10 is much better. .Pp The .Fn mktemp @@ -87,14 +102,39 @@ This avoids the race between testing for a file's existence and opening it for use. .Pp The -.Fn mkstemps +.Fn mkostemp function acts the same as .Fn mkstemp , -except it permits a suffix to exist in the template. +except that the +.Fa flags +argument may contain zero or more of the following flags for the underlying +.Xr open +system call: +.Pp +.Bl -tag -width "O_CLOEXECXX" -offset indent -compact +.It Dv O_APPEND +Append on each write. +.It Dv O_CLOEXEC +Set the close-on-exec flag on the new file descriptor. +.It Dv O_SYNC +Perform synchronous I/O operations. +.El +.Pp +The +.Fn mkstemps +and +.Fn mkostemps +functions act the same as +.Fn mkstemp +and +.Fn mkostemp , +except they permit a suffix to exist in the template. The template should be of the form .Pa /tmp/tmpXXXXXXXXXXsuffix . .Fn mkstemps -is told the length of the suffix string, i.e., +and +.Fn mkostemps +are told the length of the suffix string, i.e., .Li strlen("suffix") . .Pp The @@ -111,9 +151,11 @@ functions return a pointer to the template on success and .Dv NULL on failure. The -.Fn mkstemp +.Fn mkstemp , +.Fn mkostemp , +.Fn mkstemps , and -.Fn mkstemps +.Fn mkostemps functions return \-1 if no suitable file could be created. If any call fails, an error code is placed in the global variable .Va errno . @@ -200,6 +242,7 @@ of The .Fn mktemp , .Fn mkstemp , +.Fn mkostemp , and .Fn mkdtemp functions may set @@ -209,44 +252,70 @@ to one of the following values: .It Bq Er EINVAL The .Ar template -argument has fewer than six trailing Xs. +argument has fewer than six trailing +.Em X Ns s . .It Bq Er EEXIST All file names tried are already in use. -Consider appending more Xs to the +Consider appending more +.Em X Ns s to the .Ar template . .El .Pp The -.Fn mktemp -function may also set +.Fn mkstemps +and +.Fn mkostemps +functions may set .Va errno -to any value specified by the -.Xr lstat 2 -function. +to +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Ar template +argument length is less than +.Ar suffixlen +or it has fewer than six +.Em X Ns s +before the suffix. +.It Bq Er EEXIST +All file names tried are already in use. +Consider appending more +.Em X Ns s to the +.Ar template . +.El +.Pp +In addition, the +.Fn mkostemp +and +.Fn mkostemps +functions may also set +.Va errno +to +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa flags +is invalid. +.El .Pp The -.Fn mkstemp +.Fn mktemp function may also set .Va errno to any value specified by the -.Xr open 2 +.Xr lstat 2 function. .Pp The -.Fn mkstemps -function may also set +.Fn mkstemp , +.Fn mkostemp , +.Fn mkstemps , +and +.Fn mkostemps +functions may also set .Va errno to any value specified by the .Xr open 2 -function or, -.Bl -tag -width Er -.It Bq Er EINVAL -The -.Ar template -argument length is less than -.Ar suffixlen -or it has fewer than six Xs before the suffix. -.El +function. .Pp The .Fn mkdtemp @@ -271,7 +340,12 @@ and functions conform to the .St -p1003.1-2008 specification. -The ability to specify more than six Xs is an extension to that standard. +The ability to specify more than six +.Em X Ns s +is an extension to that standard. +The +.Fn mkostemp +function is expected to conform to a future revision of that standard. .Pp The .Fn mktemp @@ -283,7 +357,9 @@ it is no longer a part of the standard. .Pp The .Fn mkstemps -function is non-standard and should not be used if portability is required. +and +.Fn mkostemps +functions are non-standard and should not be used if portability is required. .Sh HISTORY A .Fn mktemp @@ -301,6 +377,12 @@ The .Fn mkstemps function appeared in .Ox 2.3 . +The +.Fn mkostemp +and +.Fn mkostemps +functions appeared in +.Ox 5.7 . .Sh BUGS For .Fn mktemp diff --git a/lib/libc/stdio/mktemp.c b/lib/libc/stdio/mktemp.c index cb154c4d4af..2a17e522f03 100644 --- a/lib/libc/stdio/mktemp.c +++ b/lib/libc/stdio/mktemp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mktemp.c,v 1.33 2014/05/06 22:55:27 millert Exp $ */ +/* $OpenBSD: mktemp.c,v 1.34 2014/08/31 02:21:18 guenther Exp $ */ /* * Copyright (c) 1996-1998, 2008 Theo de Raadt * Copyright (c) 1997, 2008-2009 Todd C. Miller @@ -35,12 +35,14 @@ #define NUM_CHARS (sizeof(TEMPCHARS) - 1) #define MIN_X 6 +#define MKOTEMP_FLAGS (O_APPEND | O_CLOEXEC | O_DSYNC | O_RSYNC | O_SYNC) + #ifndef nitems #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) #endif static int -mktemp_internal(char *path, int slen, int mode) +mktemp_internal(char *path, int slen, int mode, int flags) { char *start, *cp, *ep; const char *tempchars = TEMPCHARS; @@ -63,6 +65,12 @@ mktemp_internal(char *path, int slen, int mode) return(-1); } + if (flags & ~MKOTEMP_FLAGS) { + errno = EINVAL; + return(-1); + } + flags |= O_CREAT | O_EXCL | O_RDWR; + tries = INT_MAX; do { cp = start; @@ -85,7 +93,7 @@ mktemp_internal(char *path, int slen, int mode) return(errno == ENOENT ? 0 : -1); break; case MKTEMP_FILE: - fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); + fd = open(path, flags, S_IRUSR|S_IWUSR); if (fd != -1 || errno != EEXIST) return(fd); break; @@ -107,7 +115,7 @@ char *_mktemp(char *); char * _mktemp(char *path) { - if (mktemp_internal(path, 0, MKTEMP_NAME) == -1) + if (mktemp_internal(path, 0, MKTEMP_NAME, 0) == -1) return(NULL); return(path); } @@ -122,15 +130,27 @@ mktemp(char *path) } int +mkostemps(char *path, int slen, int flags) +{ + return(mktemp_internal(path, slen, MKTEMP_FILE, flags)); +} + +int mkstemp(char *path) { - return(mktemp_internal(path, 0, MKTEMP_FILE)); + return(mktemp_internal(path, 0, MKTEMP_FILE, 0)); +} + +int +mkostemp(char *path, int flags) +{ + return(mktemp_internal(path, 0, MKTEMP_FILE, flags)); } int mkstemps(char *path, int slen) { - return(mktemp_internal(path, slen, MKTEMP_FILE)); + return(mktemp_internal(path, slen, MKTEMP_FILE, 0)); } char * @@ -138,6 +158,6 @@ mkdtemp(char *path) { int error; - error = mktemp_internal(path, 0, MKTEMP_DIR); + error = mktemp_internal(path, 0, MKTEMP_DIR, 0); return(error ? NULL : path); } |