Merge "Fix incorrect parameter types for locale funcs."
diff --git a/libc/Android.mk b/libc/Android.mk
index dae254f..0670930 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -241,7 +241,6 @@
     upstream-freebsd/lib/libc/gen/sleep.c \
     upstream-freebsd/lib/libc/gen/usleep.c \
     upstream-freebsd/lib/libc/stdio/fclose.c \
-    upstream-freebsd/lib/libc/stdio/flags.c \
     upstream-freebsd/lib/libc/stdio/fopen.c \
     upstream-freebsd/lib/libc/stdlib/abs.c \
     upstream-freebsd/lib/libc/stdlib/getopt_long.c \
@@ -399,6 +398,7 @@
     upstream-openbsd/lib/libc/stdio/fgetws.c \
     upstream-openbsd/lib/libc/stdio/fileno.c \
     upstream-openbsd/lib/libc/stdio/findfp.c \
+    upstream-openbsd/lib/libc/stdio/flags.c \
     upstream-openbsd/lib/libc/stdio/fmemopen.c \
     upstream-openbsd/lib/libc/stdio/fprintf.c \
     upstream-openbsd/lib/libc/stdio/fpurge.c \
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 0dd3c27..cdb2777 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -59,7 +59,7 @@
 endif
 cpu_variant_mk := $(LOCAL_PATH)/arch-arm64/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk
 ifeq ($(wildcard $(cpu_variant_mk)),)
-$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, generic-neon, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
+$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are generic, denver64. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
 endif
 include $(cpu_variant_mk)
 libc_common_additional_dependencies += $(cpu_variank_mk)
diff --git a/libc/arch-arm64/generic-neon/bionic/memcpy.S b/libc/arch-arm64/generic-neon/bionic/memcpy.S
deleted file mode 100644
index 320f748..0000000
--- a/libc/arch-arm64/generic-neon/bionic/memcpy.S
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (c) 2012, Linaro Limited
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-       * Redistributions of source code must retain the above copyright
-         notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above copyright
-         notice, this list of conditions and the following disclaimer in the
-         documentation and/or other materials provided with the distribution.
-       * Neither the name of the Linaro nor the
-         names of its contributors may be used to endorse or promote products
-         derived from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* Assumptions:
- *
- * ARMv8-a, AArch64
- * Unaligned accesses
- *
- */
-
-#include <private/bionic_asm.h>
-
-#define dstin	x0
-#define src	x1
-#define count	x2
-#define tmp1	x3
-#define tmp1w	w3
-#define tmp2	x4
-#define tmp2w	w4
-#define tmp3	x5
-#define tmp3w	w5
-#define dst	x6
-
-#define A_l	x7
-#define A_h	x8
-#define B_l	x9
-#define B_h	x10
-#define C_l	x11
-#define C_h	x12
-#define D_l	x13
-#define D_h	x14
-
-#define QA_l q0
-#define QA_h q1
-#define QB_l q2
-#define QB_h q3
-
-ENTRY(memcpy)
-
-	mov	dst, dstin
-	cmp	count, #64
-	b.ge	.Lcpy_not_short
-	cmp	count, #15
-	b.le	.Ltail15tiny
-
-	/* Deal with small copies quickly by dropping straight into the
-	 * exit block.  */
-.Ltail63:
-	/* Copy up to 48 bytes of data.  At this point we only need the
-	 * bottom 6 bits of count to be accurate.  */
-	ands	tmp1, count, #0x30
-	b.eq	.Ltail15
-	add	dst, dst, tmp1
-	add	src, src, tmp1
-	cmp	tmp1w, #0x20
-	b.eq	1f
-	b.lt	2f
-	ldp	A_l, A_h, [src, #-48]
-	stp	A_l, A_h, [dst, #-48]
-1:
-	ldp	A_l, A_h, [src, #-32]
-	stp	A_l, A_h, [dst, #-32]
-2:
-	ldp	A_l, A_h, [src, #-16]
-	stp	A_l, A_h, [dst, #-16]
-
-.Ltail15:
-	ands	count, count, #15
-	beq	1f
-	add	src, src, count
-	ldp	A_l, A_h, [src, #-16]
-	add	dst, dst, count
-	stp	A_l, A_h, [dst, #-16]
-1:
-	ret
-
-.Ltail15tiny:
-	/* Copy up to 15 bytes of data.  Does not assume additional data
-	   being copied.  */
-	tbz	count, #3, 1f
-	ldr	tmp1, [src], #8
-	str	tmp1, [dst], #8
-1:
-	tbz	count, #2, 1f
-	ldr	tmp1w, [src], #4
-	str	tmp1w, [dst], #4
-1:
-	tbz	count, #1, 1f
-	ldrh	tmp1w, [src], #2
-	strh	tmp1w, [dst], #2
-1:
-	tbz	count, #0, 1f
-	ldrb	tmp1w, [src]
-	strb	tmp1w, [dst]
-1:
-	ret
-
-.Lcpy_not_short:
-	/* We don't much care about the alignment of DST, but we want SRC
-	 * to be 128-bit (16 byte) aligned so that we don't cross cache line
-	 * boundaries on both loads and stores.  */
-	neg	tmp2, src
-	ands	tmp2, tmp2, #15		/* Bytes to reach alignment.  */
-	b.eq	2f
-	sub	count, count, tmp2
-	/* Copy more data than needed; it's faster than jumping
-	 * around copying sub-Quadword quantities.  We know that
-	 * it can't overrun.  */
-	ldp	A_l, A_h, [src]
-	add	src, src, tmp2
-	stp	A_l, A_h, [dst]
-	add	dst, dst, tmp2
-	/* There may be less than 63 bytes to go now.  */
-	cmp	count, #63
-	b.le	.Ltail63
-2:
-	subs	count, count, #128
-	b.ge	.Lcpy_body_large
-	/* Less than 128 bytes to copy, so handle 64 here and then jump
-	 * to the tail.  */
-	ldp QA_l, QA_h, [src]
-	ldp QB_l, QB_h, [src, #32]
-	stp QA_l, QA_h, [dst]
-	stp QB_l, QB_h, [dst, #32]
-	tst	count, #0x3f
-	add	src, src, #64
-	add	dst, dst, #64
-	b.ne	.Ltail63
-	ret
-
-	/* Critical loop.  Start at a new cache line boundary.  Assuming
-	 * 64 bytes per line this ensures the entire loop is in one line.  */
-	.p2align 6
-.Lcpy_body_large:
-	/* There are at least 128 bytes to copy.  */
-	ldp QA_l, QA_h, [src, #0]
-	sub	dst, dst, #32		/* Pre-bias.  */
-	ldp QB_l, QB_h, [src, #32]!	/* src += 64 - Pre-bias.  */
-1:
-	stp QA_l, QA_h, [dst, #32]
-	ldp QA_l, QA_h, [src, #32]
-	stp QB_l, QB_h, [dst, #64]!
-	ldp QB_l, QB_h, [src, #64]!
-
-	subs	count, count, #64
-	b.ge	1b
-
-	stp QA_l, QA_h, [dst, #32]
-	stp QB_l, QB_h, [dst, #64]
-	add	src, src, #32
-	add	dst, dst, #64 + 32
-	tst	count, #0x3f
-	b.ne	.Ltail63
-	ret
-END(memcpy)
diff --git a/libc/arch-arm64/generic-neon/generic-neon.mk b/libc/arch-arm64/generic-neon/generic-neon.mk
deleted file mode 100644
index 77e3861..0000000
--- a/libc/arch-arm64/generic-neon/generic-neon.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-libc_bionic_src_files_arm64 += \
-    arch-arm64/generic/bionic/memchr.S \
-    arch-arm64/generic/bionic/memcmp.S \
-    arch-arm64/generic/bionic/memmove.S \
-    arch-arm64/generic/bionic/memset.S \
-    arch-arm64/generic/bionic/stpcpy.S \
-    arch-arm64/generic/bionic/strchr.S \
-    arch-arm64/generic/bionic/strcmp.S \
-    arch-arm64/generic/bionic/strcpy.S \
-    arch-arm64/generic/bionic/strlen.S \
-    arch-arm64/generic/bionic/strncmp.S \
-    arch-arm64/generic/bionic/strnlen.S \
-    arch-arm64/generic-neon/bionic/memcpy.S \
diff --git a/libc/bionic/lfs64_support.cpp b/libc/bionic/lfs64_support.cpp
index ab795f5..45d4f7f 100644
--- a/libc/bionic/lfs64_support.cpp
+++ b/libc/bionic/lfs64_support.cpp
@@ -17,11 +17,20 @@
 #include <ftw.h>
 #include <stdlib.h>
 
-int mkstemp64(char* filename) {
-  // Delegation will work in this case because all the transitive dependencies
-  // are already 64-bit ready. In particular, we don't have non-O_LARGEFILE
-  // open (our open is actually open64) and stat and stat64 are the same.
-  return mkstemp(filename);
+// Delegation will work in these cases because all the transitive dependencies
+// are already 64-bit ready. In particular, we don't have non-O_LARGEFILE
+// open (our open is actually open64) and stat and stat64 are the same.
+int mkstemp64(char* path) {
+  return mkstemp(path);
+}
+int mkostemp64(char* path, int flags) {
+  return mkostemp(path, flags);
+}
+int mkstemps64(char* path, int suffix_length) {
+  return mkstemps(path, suffix_length);
+}
+int mkostemps64(char* path, int suffix_length, int flags) {
+  return mkostemps(path, suffix_length, flags);
 }
 
 typedef int (*ftw_fn)(const char*, const struct stat*, int);
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index db56ce3..f57c320 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -46,6 +46,7 @@
 #endif
 
 #define O_ASYNC FASYNC
+#define O_RSYNC O_SYNC
 
 #define SPLICE_F_MOVE 1
 #define SPLICE_F_NONBLOCK 2
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 52f371b..fd2bf6c 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -59,8 +59,15 @@
 
 extern char* mkdtemp(char*);
 extern char* mktemp(char*) __warnattr("mktemp possibly used unsafely; consider using mkstemp");
-extern int mkstemp(char*);
+
+extern int mkostemp64(char*, int);
+extern int mkostemp(char*, int);
+extern int mkostemps64(char*, int, int);
+extern int mkostemps(char*, int, int);
 extern int mkstemp64(char*);
+extern int mkstemp(char*);
+extern int mkstemps64(char*, int);
+extern int mkstemps(char*, int);
 
 extern long strtol(const char *, char **, int);
 extern long long strtoll(const char *, char **, int);
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 20bc1a3..475ee1a 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -169,9 +169,7 @@
 
 extern int dup(int);
 extern int dup2(int, int);
-#if defined(__USE_GNU)
 extern int dup3(int, int, int);
-#endif
 extern int fcntl(int, int, ...);
 extern int ioctl(int, int, ...);
 extern int flock(int, int);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fdopen.c b/libc/upstream-openbsd/lib/libc/stdio/fdopen.c
index 3e47f2c..1c0c813 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fdopen.c
+++ b/libc/upstream-openbsd/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 @@
 	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 @@
 	 */
 	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/libc/upstream-freebsd/lib/libc/stdio/flags.c b/libc/upstream-openbsd/lib/libc/stdio/flags.c
similarity index 77%
rename from libc/upstream-freebsd/lib/libc/stdio/flags.c
rename to libc/upstream-openbsd/lib/libc/stdio/flags.c
index 1878c2f..d6df6da 100644
--- a/libc/upstream-freebsd/lib/libc/stdio/flags.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/flags.c
@@ -1,3 +1,4 @@
+/*	$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.
@@ -30,22 +31,15 @@
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)flags.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
 #include <sys/types.h>
 #include <sys/file.h>
 #include <stdio.h>
 #include <errno.h>
-
 #include "local.h"
 
 /*
  * Return the (stdio) flags for a given mode.  Store the flags
- * to be passed to an _open() syscall through *optr.
+ * to be passed to an open() syscall through *optr.
  * Return 0 on error.
  */
 int
@@ -78,34 +72,33 @@
 		return (0);
 	}
 
-	/* 'b' (binary) is ignored */
-	if (*mode == 'b')
-		mode++;
-
-	/* [rwa][b]\+ means read and write */
-	if (*mode == '+') {
-		mode++;
-		ret = __SRW;
-		m = O_RDWR;
-	}
-
-	/* 'b' (binary) can appear here, too -- and is ignored again */
-	if (*mode == 'b')
-		mode++;
-
-	/* 'x' means exclusive (fail if the file exists) */
-	if (*mode == 'x') {
-		mode++;
-		if (m == O_RDONLY) {
+	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
 		}
-		o |= O_EXCL;
-	}
-
-	/* set close-on-exec */
-	if (*mode == 'e')
-		o |= O_CLOEXEC;
 
 	*optr = m | o;
 	return (ret);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/freopen.c b/libc/upstream-openbsd/lib/libc/stdio/freopen.c
index 3158fb1..82717b1 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/freopen.c
+++ b/libc/upstream-openbsd/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 @@
 	 * 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/libc/upstream-openbsd/lib/libc/stdio/mktemp.c b/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
index cb154c4..2a17e52 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/mktemp.c
+++ b/libc/upstream-openbsd/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 @@
 		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 @@
 				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 *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 @@
 }
 
 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 @@
 {
 	int error;
 
-	error = mktemp_internal(path, 0, MKTEMP_DIR);
+	error = mktemp_internal(path, 0, MKTEMP_DIR, 0);
 	return(error ? NULL : path);
 }
diff --git a/tests/TemporaryFile.h b/tests/TemporaryFile.h
index c4ee2d5..5c2fe4f 100644
--- a/tests/TemporaryFile.h
+++ b/tests/TemporaryFile.h
@@ -17,24 +17,26 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-template<int (*mk_fn)(char*)>
+#include "private/bionic_macros.h"
+
+template <typename T = int (*)(char*)>
 class GenericTemporaryFile {
  public:
-  GenericTemporaryFile(const char* dirpath = NULL) {
-    if (dirpath != NULL) {
-      init(dirpath);
-    } else {
-      // Since we might be running on the host or the target, and if we're
-      // running on the host we might be running under bionic or glibc,
-      // let's just try both possible temporary directories and take the
-      // first one that works.
-      init("/data/local/tmp");
-      if (fd == -1) {
-        init("/tmp");
-      }
+  GenericTemporaryFile(T mk_fn = mkstemp) : mk_fn(mk_fn) {
+    // Since we might be running on the host or the target, and if we're
+    // running on the host we might be running under bionic or glibc,
+    // let's just try both possible temporary directories and take the
+    // first one that works.
+    init("/data/local/tmp");
+    if (fd == -1) {
+      init("/tmp");
     }
   }
 
+  GenericTemporaryFile(const char* dirpath, T mk_fn = mkstemp) : mk_fn(mk_fn) {
+    init(dirpath);
+  }
+
   ~GenericTemporaryFile() {
     close(fd);
     unlink(filename);
@@ -49,13 +51,17 @@
   char filename[1024];
 
  private:
+  T mk_fn;
+
   void init(const char* tmp_dir) {
     snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
     fd = mk_fn(filename);
   }
+
+  DISALLOW_COPY_AND_ASSIGN(GenericTemporaryFile);
 };
 
-typedef GenericTemporaryFile<mkstemp> TemporaryFile;
+typedef GenericTemporaryFile<> TemporaryFile;
 
 class TemporaryDir {
  public:
@@ -77,4 +83,5 @@
     return (mkdtemp(dirname) != NULL);
   }
 
+  DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
 };
diff --git a/tests/ftw_test.cpp b/tests/ftw_test.cpp
index 6d3a308..7ffbfe0 100644
--- a/tests/ftw_test.cpp
+++ b/tests/ftw_test.cpp
@@ -68,7 +68,7 @@
 
 TEST(ftw, ftw64) {
   TemporaryDir td;
-  GenericTemporaryFile<mkstemp64> tf(td.dirname);
+  TemporaryFile tf(td.dirname, mkstemp64);
   ftw64(td.dirname, check_ftw64, 1);
 }
 
@@ -80,6 +80,6 @@
 
 TEST(ftw, nftw64) {
   TemporaryDir td;
-  GenericTemporaryFile<mkstemp64> tf(td.dirname);
+  TemporaryFile tf(td.dirname, mkstemp64);
   nftw64(td.dirname, check_nftw64, 1, 0);
 }
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index c01ab68..6a653b4 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -756,3 +756,43 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
+
+TEST(stdio, fdopen_CLOEXEC) {
+  int fd = open("/proc/version", O_RDONLY);
+  ASSERT_TRUE(fd != -1);
+
+  // This fd doesn't have O_CLOEXEC...
+  int flags = fcntl(fd, F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(0, flags & FD_CLOEXEC);
+
+  FILE* fp = fdopen(fd, "re");
+  ASSERT_TRUE(fp != NULL);
+
+  // ...but the new one does.
+  flags = fcntl(fileno(fp), F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+
+  fclose(fp);
+  close(fd);
+}
+
+TEST(stdio, freopen_CLOEXEC) {
+  FILE* fp = fopen("/proc/version", "r");
+  ASSERT_TRUE(fp != NULL);
+
+  // This FILE* doesn't have O_CLOEXEC...
+  int flags = fcntl(fileno(fp), F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(0, flags & FD_CLOEXEC);
+
+  fp = freopen("/proc/version", "re", fp);
+
+  // ...but the new one does.
+  flags = fcntl(fileno(fp), F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+
+  fclose(fp);
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 667ccd6..e814ef7 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -162,19 +162,33 @@
   ASSERT_EXIT(TestBug57421_main(), ::testing::ExitedWithCode(0), "");
 }
 
+TEST(stdlib, mkostemp64) {
+  TemporaryFile tf([](char* path) { return mkostemp64(path, O_CLOEXEC); });
+  int flags = fcntl(tf.fd, F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+}
+
+TEST(stdlib, mkostemp) {
+  TemporaryFile tf([](char* path) { return mkostemp(path, O_CLOEXEC); });
+  int flags = fcntl(tf.fd, F_GETFD);
+  ASSERT_TRUE(flags != -1);
+  ASSERT_EQ(FD_CLOEXEC, flags & FD_CLOEXEC);
+}
+
+TEST(stdlib, mkstemp64) {
+  TemporaryFile tf(mkstemp64);
+  struct stat64 sb;
+  ASSERT_EQ(0, fstat64(tf.fd, &sb));
+  ASSERT_EQ(O_LARGEFILE, fcntl(tf.fd, F_GETFL) & O_LARGEFILE);
+}
+
 TEST(stdlib, mkstemp) {
   TemporaryFile tf;
   struct stat sb;
   ASSERT_EQ(0, fstat(tf.fd, &sb));
 }
 
-TEST(stdlib, mkstemp64) {
-  GenericTemporaryFile<mkstemp64> tf;
-  struct stat64 sb;
-  ASSERT_EQ(0, fstat64(tf.fd, &sb));
-  ASSERT_EQ(O_LARGEFILE, fcntl(tf.fd, F_GETFL) & O_LARGEFILE);
-}
-
 TEST(stdlib, system) {
   int status;