From 0790b2465ab8f2f9b0d86869a896d63358b00099 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Mon, 12 Nov 2018 12:29:14 -0800 Subject: [PATCH] base: move TemporaryFile and TemporaryDir to android-base/file.h Allow a wider legitimate audience to use TemporaryFile and TemporaryDir by moving them from android-base/test_utils.h to android-base/file.h. Test: compile Bug: 119313545 Change-Id: Ie558c5873ce5b3937914918b6bfb427e5b61d0da --- base/file.cpp | 97 +++++++++++++++++++++++++ base/include/android-base/file.h | 38 ++++++++++ base/include/android-base/test_utils.h | 37 +--------- base/test_utils.cpp | 98 -------------------------- 4 files changed, 136 insertions(+), 134 deletions(-) diff --git a/base/file.cpp b/base/file.cpp index 3834ed42a..e4407d073 100644 --- a/base/file.cpp +++ b/base/file.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,10 +39,105 @@ #include #endif #if defined(_WIN32) +#include #include #define O_NOFOLLOW 0 +#define OS_PATH_SEPARATOR '\\' +#else +#define OS_PATH_SEPARATOR '/' #endif +#ifdef _WIN32 +int mkstemp(char* template_name) { + if (_mktemp(template_name) == nullptr) { + return -1; + } + // Use open() to match the close() that TemporaryFile's destructor does. + // Use O_BINARY to match base file APIs. + return open(template_name, O_CREAT | O_EXCL | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR); +} + +char* mkdtemp(char* template_name) { + if (_mktemp(template_name) == nullptr) { + return nullptr; + } + if (_mkdir(template_name) == -1) { + return nullptr; + } + return template_name; +} +#endif + +namespace { + +std::string GetSystemTempDir() { +#if defined(__ANDROID__) + const char* tmpdir = "/data/local/tmp"; + if (access(tmpdir, R_OK | W_OK | X_OK) == 0) { + return tmpdir; + } + // Tests running in app context can't access /data/local/tmp, + // so try current directory if /data/local/tmp is not accessible. + return "."; +#elif defined(_WIN32) + char tmp_dir[MAX_PATH]; + DWORD result = GetTempPathA(sizeof(tmp_dir), tmp_dir); + CHECK_NE(result, 0ul) << "GetTempPathA failed, error: " << GetLastError(); + CHECK_LT(result, sizeof(tmp_dir)) << "path truncated to: " << result; + + // GetTempPath() returns a path with a trailing slash, but init() + // does not expect that, so remove it. + CHECK_EQ(tmp_dir[result - 1], '\\'); + tmp_dir[result - 1] = '\0'; + return tmp_dir; +#else + return "/tmp"; +#endif +} + +} // namespace + +TemporaryFile::TemporaryFile() { + init(GetSystemTempDir()); +} + +TemporaryFile::TemporaryFile(const std::string& tmp_dir) { + init(tmp_dir); +} + +TemporaryFile::~TemporaryFile() { + if (fd != -1) { + close(fd); + } + if (remove_file_) { + unlink(path); + } +} + +int TemporaryFile::release() { + int result = fd; + fd = -1; + return result; +} + +void TemporaryFile::init(const std::string& tmp_dir) { + snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(), OS_PATH_SEPARATOR); + fd = mkstemp(path); +} + +TemporaryDir::TemporaryDir() { + init(GetSystemTempDir()); +} + +TemporaryDir::~TemporaryDir() { + rmdir(path); +} + +bool TemporaryDir::init(const std::string& tmp_dir) { + snprintf(path, sizeof(path), "%s%cTemporaryDir-XXXXXX", tmp_dir.c_str(), OS_PATH_SEPARATOR); + return (mkdtemp(path) != nullptr); +} + namespace android { namespace base { diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h index 86d537d76..80d71346d 100644 --- a/base/include/android-base/file.h +++ b/base/include/android-base/file.h @@ -18,8 +18,10 @@ #include #include + #include +#include #include "android-base/off64_t.h" #if !defined(_WIN32) && !defined(O_BINARY) @@ -32,6 +34,42 @@ #define O_CLOEXEC O_NOINHERIT #endif +class TemporaryFile { + public: + TemporaryFile(); + explicit TemporaryFile(const std::string& tmp_dir); + ~TemporaryFile(); + + // Release the ownership of fd, caller is reponsible for closing the + // fd or stream properly. + int release(); + // Don't remove the temporary file in the destructor. + void DoNotRemove() { remove_file_ = false; } + + int fd; + char path[1024]; + + private: + void init(const std::string& tmp_dir); + + bool remove_file_ = true; + + DISALLOW_COPY_AND_ASSIGN(TemporaryFile); +}; + +class TemporaryDir { + public: + TemporaryDir(); + ~TemporaryDir(); + + char path[1024]; + + private: + bool init(const std::string& tmp_dir); + + DISALLOW_COPY_AND_ASSIGN(TemporaryDir); +}; + namespace android { namespace base { diff --git a/base/include/android-base/test_utils.h b/base/include/android-base/test_utils.h index 2abe68e02..b20f27846 100644 --- a/base/include/android-base/test_utils.h +++ b/base/include/android-base/test_utils.h @@ -19,44 +19,9 @@ #include #include +#include #include -class TemporaryFile { - public: - TemporaryFile(); - explicit TemporaryFile(const std::string& tmp_dir); - ~TemporaryFile(); - - // Release the ownership of fd, caller is reponsible for closing the - // fd or stream properly. - int release(); - // Don't remove the temporary file in the destructor. - void DoNotRemove() { remove_file_ = false; } - - int fd; - char path[1024]; - - private: - void init(const std::string& tmp_dir); - - bool remove_file_ = true; - - DISALLOW_COPY_AND_ASSIGN(TemporaryFile); -}; - -class TemporaryDir { - public: - TemporaryDir(); - ~TemporaryDir(); - - char path[1024]; - - private: - bool init(const std::string& tmp_dir); - - DISALLOW_COPY_AND_ASSIGN(TemporaryDir); -}; - class CapturedStdFd { public: CapturedStdFd(int std_fd); diff --git a/base/test_utils.cpp b/base/test_utils.cpp index 4d9466b30..36b4cdfa4 100644 --- a/base/test_utils.cpp +++ b/base/test_utils.cpp @@ -22,109 +22,11 @@ #include #include -#if defined(_WIN32) -#include -#include -#define OS_PATH_SEPARATOR '\\' -#else -#define OS_PATH_SEPARATOR '/' -#endif - #include #include #include -#ifdef _WIN32 -int mkstemp(char* template_name) { - if (_mktemp(template_name) == nullptr) { - return -1; - } - // Use open() to match the close() that TemporaryFile's destructor does. - // Use O_BINARY to match base file APIs. - return open(template_name, O_CREAT | O_EXCL | O_RDWR | O_BINARY, - S_IRUSR | S_IWUSR); -} - -char* mkdtemp(char* template_name) { - if (_mktemp(template_name) == nullptr) { - return nullptr; - } - if (_mkdir(template_name) == -1) { - return nullptr; - } - return template_name; -} -#endif - -static std::string GetSystemTempDir() { -#if defined(__ANDROID__) - const char* tmpdir = "/data/local/tmp"; - if (access(tmpdir, R_OK | W_OK | X_OK) == 0) { - return tmpdir; - } - // Tests running in app context can't access /data/local/tmp, - // so try current directory if /data/local/tmp is not accessible. - return "."; -#elif defined(_WIN32) - char tmp_dir[MAX_PATH]; - DWORD result = GetTempPathA(sizeof(tmp_dir), tmp_dir); - CHECK_NE(result, 0ul) << "GetTempPathA failed, error: " << GetLastError(); - CHECK_LT(result, sizeof(tmp_dir)) << "path truncated to: " << result; - - // GetTempPath() returns a path with a trailing slash, but init() - // does not expect that, so remove it. - CHECK_EQ(tmp_dir[result - 1], '\\'); - tmp_dir[result - 1] = '\0'; - return tmp_dir; -#else - return "/tmp"; -#endif -} - -TemporaryFile::TemporaryFile() { - init(GetSystemTempDir()); -} - -TemporaryFile::TemporaryFile(const std::string& tmp_dir) { - init(tmp_dir); -} - -TemporaryFile::~TemporaryFile() { - if (fd != -1) { - close(fd); - } - if (remove_file_) { - unlink(path); - } -} - -int TemporaryFile::release() { - int result = fd; - fd = -1; - return result; -} - -void TemporaryFile::init(const std::string& tmp_dir) { - snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(), - OS_PATH_SEPARATOR); - fd = mkstemp(path); -} - -TemporaryDir::TemporaryDir() { - init(GetSystemTempDir()); -} - -TemporaryDir::~TemporaryDir() { - rmdir(path); -} - -bool TemporaryDir::init(const std::string& tmp_dir) { - snprintf(path, sizeof(path), "%s%cTemporaryDir-XXXXXX", tmp_dir.c_str(), - OS_PATH_SEPARATOR); - return (mkdtemp(path) != nullptr); -} - CapturedStdFd::CapturedStdFd(int std_fd) : std_fd_(std_fd), old_fd_(-1) { Start(); }