Merge "Make tmpfile() respect $TMPDIR."
This commit is contained in:
commit
17b2bae190
2 changed files with 31 additions and 23 deletions
|
@ -51,6 +51,9 @@ static FILE* __fd_to_fp(int fd) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// O_TMPFILE isn't available until Linux 3.11, so we fall back to this on
|
||||||
|
// older kernels. AOSP was on a new enough kernel in the Lollipop timeframe,
|
||||||
|
// so this code should be obsolete by 2025.
|
||||||
static FILE* __tmpfile_dir_legacy(const char* tmp_dir) {
|
static FILE* __tmpfile_dir_legacy(const char* tmp_dir) {
|
||||||
char* path = nullptr;
|
char* path = nullptr;
|
||||||
if (asprintf(&path, "%s/tmp.XXXXXXXXXX", tmp_dir) == -1) {
|
if (asprintf(&path, "%s/tmp.XXXXXXXXXX", tmp_dir) == -1) {
|
||||||
|
@ -79,25 +82,18 @@ static FILE* __tmpfile_dir_legacy(const char* tmp_dir) {
|
||||||
return __fd_to_fp(fd);
|
return __fd_to_fp(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE* __tmpfile_dir(const char* tmp_dir) {
|
const char* __get_TMPDIR() {
|
||||||
int fd = open(tmp_dir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
|
// Use $TMPDIR if set, or fall back to /data/local/tmp otherwise.
|
||||||
if (fd == -1) return __tmpfile_dir_legacy(tmp_dir);
|
// Useless for apps, but good enough for the shell.
|
||||||
return __fd_to_fp(fd);
|
const char* tmpdir = getenv("TMPDIR");
|
||||||
|
return (tmpdir == nullptr) ? "/data/local/tmp" : tmpdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* tmpfile() {
|
FILE* tmpfile() {
|
||||||
// TODO: get this app's temporary directory from the framework ("/data/data/app/cache").
|
const char* tmpdir = __get_TMPDIR();
|
||||||
|
int fd = open(tmpdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
|
||||||
// $EXTERNAL_STORAGE turns out not to be very useful because it doesn't support hard links.
|
if (fd == -1) return __tmpfile_dir_legacy(tmpdir);
|
||||||
// This means we can't do the usual trick of calling unlink before handing the file back.
|
return __fd_to_fp(fd);
|
||||||
|
|
||||||
FILE* fp = __tmpfile_dir("/data/local/tmp");
|
|
||||||
if (fp == nullptr) {
|
|
||||||
// P_tmpdir is "/tmp/", but POSIX explicitly says that tmpdir(3) should try P_tmpdir before
|
|
||||||
// giving up. This is potentially useful for bionic on the host anyway.
|
|
||||||
fp = __tmpfile_dir(P_tmpdir);
|
|
||||||
}
|
|
||||||
return fp;
|
|
||||||
}
|
}
|
||||||
__strong_alias(tmpfile64, tmpfile);
|
__strong_alias(tmpfile64, tmpfile);
|
||||||
|
|
||||||
|
@ -107,7 +103,7 @@ char* tempnam(const char* dir, const char* prefix) {
|
||||||
// since we can't easily remove it...
|
// since we can't easily remove it...
|
||||||
|
|
||||||
// $TMPDIR overrides any directory passed in.
|
// $TMPDIR overrides any directory passed in.
|
||||||
char* tmpdir = getenv("TMPDIR");
|
const char* tmpdir = getenv("TMPDIR");
|
||||||
if (tmpdir != nullptr) dir = tmpdir;
|
if (tmpdir != nullptr) dir = tmpdir;
|
||||||
|
|
||||||
// If we still have no directory, we'll give you a default.
|
// If we still have no directory, we'll give you a default.
|
||||||
|
@ -136,12 +132,7 @@ char* tmpnam(char* s) {
|
||||||
static char buf[L_tmpnam];
|
static char buf[L_tmpnam];
|
||||||
if (s == nullptr) s = buf;
|
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.
|
// Make up a mktemp(3) template and defer to it for the real work.
|
||||||
snprintf(s, L_tmpnam, "%s/tmpnam.XXXXXXXXXX", dir);
|
snprintf(s, L_tmpnam, "%s/tmpnam.XXXXXXXXXX", __get_TMPDIR());
|
||||||
return mktemp(s);
|
return mktemp(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
#include <android-base/file.h>
|
#include <android-base/file.h>
|
||||||
#include <android-base/silent_death_test.h>
|
#include <android-base/silent_death_test.h>
|
||||||
|
#include <android-base/strings.h>
|
||||||
#include <android-base/test_utils.h>
|
#include <android-base/test_utils.h>
|
||||||
#include <android-base/unique_fd.h>
|
#include <android-base/unique_fd.h>
|
||||||
|
|
||||||
|
@ -140,6 +141,22 @@ TEST(STDIO_TEST, tmpfile64) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(STDIO_TEST, tmpfile_TMPDIR) {
|
||||||
|
TemporaryDir td;
|
||||||
|
setenv("TMPDIR", td.path, 1);
|
||||||
|
|
||||||
|
FILE* fp = tmpfile();
|
||||||
|
ASSERT_TRUE(fp != nullptr);
|
||||||
|
|
||||||
|
std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fileno(fp));
|
||||||
|
char path[PATH_MAX];
|
||||||
|
ASSERT_GT(readlink(fd_path.c_str(), path, sizeof(path)), 0);
|
||||||
|
// $TMPDIR influenced where our temporary file ended up?
|
||||||
|
ASSERT_TRUE(android::base::StartsWith(path, td.path)) << path;
|
||||||
|
// And we used O_TMPFILE, right?
|
||||||
|
ASSERT_TRUE(android::base::EndsWith(path, " (deleted)")) << path;
|
||||||
|
}
|
||||||
|
|
||||||
TEST(STDIO_TEST, dprintf) {
|
TEST(STDIO_TEST, dprintf) {
|
||||||
TemporaryFile tf;
|
TemporaryFile tf;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue