aboutsummaryrefslogtreecommitdiff
path: root/libc/bionic/tmpfile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libc/bionic/tmpfile.cpp')
-rw-r--r--libc/bionic/tmpfile.cpp109
1 files changed, 78 insertions, 31 deletions
diff --git a/libc/bionic/tmpfile.cpp b/libc/bionic/tmpfile.cpp
index 4378e84ab..3d04610a4 100644
--- a/libc/bionic/tmpfile.cpp
+++ b/libc/bionic/tmpfile.cpp
@@ -31,56 +31,58 @@
*/
#include <errno.h>
+#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "private/ErrnoRestorer.h"
-#include "private/ScopedSignalBlocker.h"
-static FILE* __tmpfile_dir(const char* tmp_dir) {
+static FILE* __fd_to_fp(int fd) {
+ FILE* fp = fdopen(fd, "w+");
+ if (fp != nullptr) return fp;
+
+ ErrnoRestorer errno_restorer;
+ close(fd);
+ return nullptr;
+}
+
+static FILE* __tmpfile_dir_legacy(const char* tmp_dir) {
char* path = nullptr;
if (asprintf(&path, "%s/tmp.XXXXXXXXXX", tmp_dir) == -1) {
return nullptr;
}
- int fd;
- {
- ScopedSignalBlocker ssb;
- fd = mkstemp(path);
- if (fd == -1) {
- free(path);
- return nullptr;
- }
-
- // Unlink the file now so that it's removed when closed.
- unlink(path);
+ int fd = mkstemp(path);
+ if (fd == -1) {
free(path);
-
- // Can we still use the file now it's unlinked?
- // File systems without hard link support won't have the usual Unix semantics.
- struct stat sb;
- int rc = fstat(fd, &sb);
- if (rc == -1) {
- ErrnoRestorer errno_restorer;
- close(fd);
- return nullptr;
- }
+ return nullptr;
}
- // Turn the file descriptor into a FILE*.
- FILE* fp = fdopen(fd, "w+");
- if (fp != nullptr) {
- return fp;
+ // Unlink the file now so that it's removed when closed.
+ unlink(path);
+ free(path);
+
+ // Can we still use the file now it's unlinked?
+ // File systems without hard link support won't have the usual Unix semantics.
+ struct stat sb;
+ if (fstat(fd, &sb) == -1) {
+ ErrnoRestorer errno_restorer;
+ close(fd);
+ return nullptr;
}
- // Failure. Clean up. We already unlinked, so we just need to close.
- ErrnoRestorer errno_restorer;
- close(fd);
- return nullptr;
+ return __fd_to_fp(fd);
+}
+
+static FILE* __tmpfile_dir(const char* tmp_dir) {
+ int fd = open(tmp_dir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
+ if (fd == -1) return __tmpfile_dir_legacy(tmp_dir);
+ return __fd_to_fp(fd);
}
FILE* tmpfile() {
@@ -98,3 +100,48 @@ FILE* tmpfile() {
return fp;
}
__strong_alias(tmpfile64, tmpfile);
+
+char* tempnam(const char* dir, const char* prefix) {
+ // This function is a terrible idea, marked deprecated in our headers,
+ // and marked obsolescent by POSIX.1-2008, but we make some effort anyway
+ // since we can't easily remove it...
+
+ // $TMPDIR overrides any directory passed in.
+ char* tmpdir = getenv("TMPDIR");
+ if (tmpdir != nullptr) dir = tmpdir;
+
+ // If we still have no directory, we'll give you a default.
+ // It's useless for apps, but good enough for the shell.
+ if (dir == nullptr) dir = "/data/local/tmp";
+
+ // Default prefix?
+ if (prefix == nullptr) prefix = "tempnam.";
+
+ // Make up a mktemp(3) template and defer to it for the real work.
+ char* path = nullptr;
+ if (asprintf(&path, "%s/%sXXXXXXXXXX", dir, prefix) == -1) return nullptr;
+ if (mktemp(path) == nullptr) {
+ free(path);
+ return nullptr;
+ }
+ return path;
+}
+
+char* tmpnam(char* s) {
+ // This function is a terrible idea, marked deprecated in our headers,
+ // and marked obsolescent by POSIX-1.2008, but we make some effort anyway
+ // since we can't easily remove it...
+
+ // Default buffer?
+ static char buf[L_tmpnam];
+ if (s == nullptr) s = buf;
+
+ // Use $TMPDIR if set, or fall back to /data/local/tmp otherwise.
+ // Useless for apps, but good enough for the shell.
+ const char* dir = getenv("TMPDIR");
+ if (dir == nullptr) dir = "/data/local/tmp";
+
+ // Make up a mktemp(3) template and defer to it for the real work.
+ snprintf(s, L_tmpnam, "%s/tmpnam.XXXXXXXXXX", dir);
+ return mktemp(s);
+}