Simplify and improve tempnam() and tmpnam().
They're both obsolescent in POSIX.1-2008, and you really shouldn't be
using them, but since we can't actually delete them...
This change makes them both obey $TMPDIR if set, and fall back to
/data/local/tmp otherwise. That's as good as we've managed for anything
else such as tmpfile(3).
Also add some tests.
Bug: http://b/174682340
Test: treehugger
Change-Id: Ieef99dcc2062f84b2b7cbae046787fdfe975e772
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index c21c3b8..5680f95 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -33,6 +33,7 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/test_utils.h>
#include <android-base/unique_fd.h>
#include "BionicDeathTest.h"
@@ -2816,3 +2817,69 @@
ASSERT_TRUE(fp == nullptr);
ASSERT_EQ(ENOENT, errno);
}
+
+static void tempnam_test(bool has_TMPDIR, const char* dir, const char* prefix, const char* re) {
+ if (has_TMPDIR) {
+ setenv("TMPDIR", "/my/tmp/dir", 1);
+ } else {
+ unsetenv("TMPDIR");
+ }
+ char* s1 = tempnam(dir, prefix);
+ char* s2 = tempnam(dir, prefix);
+ ASSERT_MATCH(s1, re);
+ ASSERT_MATCH(s2, re);
+ ASSERT_STRNE(s1, s2);
+ free(s1);
+ free(s2);
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_system_prefix_with_TMPDIR) {
+ tempnam_test(true, nullptr, nullptr, "^/my/tmp/dir/.*");
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_system_prefix_without_TMPDIR) {
+ tempnam_test(false, nullptr, nullptr, "^/data/local/tmp/.*");
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_user_prefix_with_TMPDIR) {
+ tempnam_test(true, nullptr, "prefix", "^/my/tmp/dir/prefix.*");
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_user_prefix_without_TMPDIR) {
+ tempnam_test(false, nullptr, "prefix", "^/data/local/tmp/prefix.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_system_prefix_with_TMPDIR) {
+ tempnam_test(true, "/a/b/c", nullptr, "^/my/tmp/dir/.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_system_prefix_without_TMPDIR) {
+ tempnam_test(false, "/a/b/c", nullptr, "^/a/b/c/.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_user_prefix_with_TMPDIR) {
+ tempnam_test(true, "/a/b/c", "prefix", "^/my/tmp/dir/prefix.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_user_prefix_without_TMPDIR) {
+ tempnam_test(false, "/a/b/c", "prefix", "^/a/b/c/prefix.*");
+}
+
+static void tmpnam_test(char* s) {
+ char s1[L_tmpnam], s2[L_tmpnam];
+
+ strcpy(s1, tmpnam(s));
+ strcpy(s2, tmpnam(s));
+ ASSERT_MATCH(s1, "/tmp/.*");
+ ASSERT_MATCH(s2, "/tmp/.*");
+ ASSERT_STRNE(s1, s2);
+}
+
+TEST(STDIO_TEST, tmpnam) {
+ tmpnam_test(nullptr);
+}
+
+TEST(STDIO_TEST, tmpnam_buf) {
+ char buf[L_tmpnam];
+ tmpnam_test(buf);
+}