summaryrefslogtreecommitdiff
path: root/lib/libc/stdio
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2014-08-31 02:21:19 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2014-08-31 02:21:19 +0000
commit13ce210035fe567fec6650d96844a253e5447c54 (patch)
tree280df60d17551f05f4b39ff8aeff8f325f88f436 /lib/libc/stdio
parentb69e25c758b3865a13793b76dfdbaba108817277 (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.inc4
-rw-r--r--lib/libc/stdio/fdopen.c10
-rw-r--r--lib/libc/stdio/flags.c35
-rw-r--r--lib/libc/stdio/fopen.359
-rw-r--r--lib/libc/stdio/freopen.c4
-rw-r--r--lib/libc/stdio/mktemp.3148
-rw-r--r--lib/libc/stdio/mktemp.c34
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);
}