summaryrefslogtreecommitdiff
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
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@
-rw-r--r--include/stdlib.h10
-rw-r--r--lib/libc/gen/popen.314
-rw-r--r--lib/libc/gen/popen.c57
-rw-r--r--lib/libc/gen/posix_spawn.c15
-rw-r--r--lib/libc/gen/posix_spawn_file_actions_addopen.310
-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
12 files changed, 301 insertions, 99 deletions
diff --git a/include/stdlib.h b/include/stdlib.h
index 495b01bf5e7..520a1b1f9ba 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: stdlib.h,v 1.59 2014/07/09 16:57:49 beck Exp $ */
+/* $OpenBSD: stdlib.h,v 1.60 2014/08/31 02:21:18 guenther Exp $ */
/* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */
/*-
@@ -256,6 +256,13 @@ char *mkdtemp(char *);
int getsubopt(char **, char * const *, char **);
#endif
+/*
+ * The Open Group Base Specifications, post-Issue 7
+ */
+#if __BSD_VISIBLE
+int mkostemp(char *, int);
+#endif
+
#if __BSD_VISIBLE
void *alloca(size_t);
@@ -285,6 +292,7 @@ void setprogname(const char *);
extern char *suboptarg; /* getsubopt(3) external variable */
int mkstemps(char *, int);
+int mkostemps(char *, int, int);
int heapsort(void *, size_t, size_t, int (*)(const void *, const void *));
int mergesort(void *, size_t, size_t, int (*)(const void *, const void *));
diff --git a/lib/libc/gen/popen.3 b/lib/libc/gen/popen.3
index dfadbd7f8c8..ba1b8cfc47f 100644
--- a/lib/libc/gen/popen.3
+++ b/lib/libc/gen/popen.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: popen.3,v 1.18 2014/01/19 10:39:00 schwarze Exp $
+.\" $OpenBSD: popen.3,v 1.19 2014/08/31 02:21:18 guenther Exp $
.\"
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -27,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd $Mdocdate: January 19 2014 $
+.Dd $Mdocdate: August 31 2014 $
.Dt POPEN 3
.Os
.Sh NAME
@@ -65,10 +65,20 @@ The
argument is a pointer to a NUL-terminated
string which must be either
.Qq r
+or
+.Qq re
for reading
or
.Qq w
+or
+.Qq we
for writing.
+If the letter
+.Qq e
+is present in the string then the close-on-exec flag shall be set on the
+file descriptor underlying the
+.Vt FILE
+that is returned.
.Pp
The return value from
.Fn popen
diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c
index d7c6c61731f..973291d2dc8 100644
--- a/lib/libc/gen/popen.c
+++ b/lib/libc/gen/popen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: popen.c,v 1.18 2007/11/26 19:26:46 kurt Exp $ */
+/* $OpenBSD: popen.c,v 1.19 2014/08/31 02:21:18 guenther Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
@@ -36,11 +36,13 @@
#include <signal.h>
#include <errno.h>
+#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <paths.h>
+#include <wchar.h>
#include "thread_private.h"
static struct pid {
@@ -57,9 +59,11 @@ popen(const char *program, const char *type)
struct pid * volatile cur;
FILE *iop;
int pdes[2];
+ int target;
pid_t pid;
- if ((*type != 'r' && *type != 'w') || type[1] != '\0') {
+ if ((*type != 'r' && *type != 'w') ||
+ (type[1] != '\0' && (type[1] != 'e' || type[2] != '\0'))) {
errno = EINVAL;
return (NULL);
}
@@ -67,7 +71,7 @@ popen(const char *program, const char *type)
if ((cur = malloc(sizeof(struct pid))) == NULL)
return (NULL);
- if (pipe(pdes) < 0) {
+ if (pipe2(pdes, O_CLOEXEC) < 0) {
free(cur);
return (NULL);
}
@@ -84,6 +88,7 @@ popen(const char *program, const char *type)
case 0: /* Child. */
{
struct pid *pcur;
+
/*
* because vfork() instead of fork(), must leak FILE *,
* but luckily we are terminally headed for an execl()
@@ -91,26 +96,18 @@ popen(const char *program, const char *type)
for (pcur = pidlist; pcur; pcur = pcur->next)
close(fileno(pcur->fp));
- if (*type == 'r') {
- int tpdes1 = pdes[1];
-
- (void) close(pdes[0]);
- /*
- * We must NOT modify pdes, due to the
- * semantics of vfork.
- */
- if (tpdes1 != STDOUT_FILENO) {
- (void)dup2(tpdes1, STDOUT_FILENO);
- (void)close(tpdes1);
- tpdes1 = STDOUT_FILENO;
- }
+ target = *type == 'r';
+ if (pdes[target] != target) {
+ if (dup2(pdes[target], target) == -1)
+ _exit(127);
} else {
- (void)close(pdes[1]);
- if (pdes[0] != STDIN_FILENO) {
- (void)dup2(pdes[0], STDIN_FILENO);
- (void)close(pdes[0]);
- }
+ int flags = fcntl(pdes[target], F_GETFD);
+ if (flags == -1 || ((flags & FD_CLOEXEC) &&
+ fcntl(pdes[target], F_SETFD, flags & ~FD_CLOEXEC)
+ == -1))
+ _exit(127);
}
+
execl(_PATH_BSHELL, "sh", "-c", program, (char *)NULL);
_exit(127);
/* NOTREACHED */
@@ -119,13 +116,10 @@ popen(const char *program, const char *type)
_MUTEX_UNLOCK(&pidlist_lock);
/* Parent; assume fdopen can't fail. */
- if (*type == 'r') {
- iop = fdopen(pdes[0], type);
- (void)close(pdes[1]);
- } else {
- iop = fdopen(pdes[1], type);
- (void)close(pdes[0]);
- }
+ target = *type == 'w';
+ iop = fdopen(pdes[target], type);
+ fwide(iop, -1);
+ (void)close(pdes[!target]);
/* Link into list of file descriptors. */
cur->fp = iop;
@@ -135,6 +129,13 @@ popen(const char *program, const char *type)
pidlist = cur;
_MUTEX_UNLOCK(&pidlist_lock);
+ /* now that it's in the list, clear FD_CLOEXEC if unwanted */
+ if (type[1] != 'e') {
+ int flags = fcntl(pdes[target], F_GETFD);
+ if (flags != -1)
+ fcntl(pdes[target], F_SETFD, flags & ~FD_CLOEXEC);
+ }
+
return (iop);
}
diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c
index acfe68c63c5..c45080b1a11 100644
--- a/lib/libc/gen/posix_spawn.c
+++ b/lib/libc/gen/posix_spawn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: posix_spawn.c,v 1.3 2012/12/05 23:20:00 deraadt Exp $ */
+/* $OpenBSD: posix_spawn.c,v 1.4 2014/08/31 02:21:18 guenther Exp $ */
/*-
* Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
* All rights reserved.
@@ -155,8 +155,17 @@ process_file_actions_entry(posix_spawn_file_actions_entry_t *fae)
}
break;
case FAE_DUP2:
- /* Perform a dup2() */
- if (dup2(fae->fae_fildes, fae->fae_newfildes) == -1)
+ /*
+ * Perform a dup2(), making sure the FD_CLOEXEC flag is clear
+ */
+ if (fae->fae_fildes == fae->fae_newfildes) {
+ int flags = fcntl(fd, F_GETFD);
+
+ if (flags == -1 ||
+ ((flags & FD_CLOEXEC) &&
+ fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC) == -1))
+ return (errno);
+ } else if (dup2(fae->fae_fildes, fae->fae_newfildes) == -1)
return (errno);
break;
case FAE_CLOSE:
diff --git a/lib/libc/gen/posix_spawn_file_actions_addopen.3 b/lib/libc/gen/posix_spawn_file_actions_addopen.3
index 519a9a6f92f..b00ee325e8c 100644
--- a/lib/libc/gen/posix_spawn_file_actions_addopen.3
+++ b/lib/libc/gen/posix_spawn_file_actions_addopen.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: posix_spawn_file_actions_addopen.3,v 1.6 2013/07/16 15:21:11 schwarze Exp $
+.\" $OpenBSD: posix_spawn_file_actions_addopen.3,v 1.7 2014/08/31 02:21:18 guenther Exp $
.\"
.\" Copyright (c) 2012 Marc Espie <espie@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: July 16 2013 $
+.Dd $Mdocdate: August 31 2014 $
.Dt POSIX_SPAWN_FILE_ACTIONS_ADDOPEN 3
.Os
.Sh NAME
@@ -61,6 +61,12 @@ dup2(fildes, newfildes);
.Ed
.Pp
to be called.
+In addition, the action will cause the close-on-exec flag to be cleared on
+.Fa newfildes ,
+even if
+.Fa newfildes
+equals
+.Fa fildes .
.It
The
.Fn posix_spawn_file_actions_addopen
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);
}