CLOEXEC support in fdopen, freopen, and mkostemp/mkostemps.
Change-Id: I74ea88e0d4973d6ab3c57da7d8bb643c31592b14
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;