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);
+}