1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/googletest/custom/gtest/internal/custom/chrome_custom_temp_dir.h"
6 #include "third_party/googletest/src/googletest/include/gtest/internal/gtest-port.h"
7 #if GTEST_OS_WINDOWS
8 #include <windows.h>
9 #endif // GTEST_OS_WINDOWS
10
11 namespace testing {
12
13 namespace {
14
15 // The temporary directory read from the OS canonical environment variable.
16 //
17 // Returns an empty string if the environment variable is not set. The returned
18 // string may or may not end with the OS-specific path separator. The path is
19 // not guaranteed to point to an existing directory. The directory it points to
20 // is not guaranteed to be writable by the application.
ChromeGetEnvTempDir()21 std::string ChromeGetEnvTempDir() {
22 #if GTEST_OS_WINDOWS_MOBILE
23 const char* env_result = internal::posix::GetEnv("TEMP");
24 #elif GTEST_OS_WINDOWS
25 char temp_dir_path[_MAX_PATH + 1] = {'\0'}; // NOLINT
26 if (::GetTempPathA(sizeof(temp_dir_path), temp_dir_path) != 0)
27 return temp_dir_path;
28 const char* env_result = internal::posix::GetEnv("TEMP");
29 #else
30 const char* env_result = internal::posix::GetEnv("TMPDIR");
31 #endif // GETST_OS_WINDOWS
32
33 if (env_result == nullptr)
34 return std::string();
35 return env_result;
36 }
37
38 } // namespace
39
40 // returns temp directory for tests.
ChromeCustomTempDir()41 std::string ChromeCustomTempDir() {
42 std::string temp_dir = ChromeGetEnvTempDir();
43 if (!temp_dir.empty()) {
44 if (temp_dir.back() != GTEST_PATH_SEP_[0])
45 temp_dir.push_back(GTEST_PATH_SEP_[0]);
46 return temp_dir;
47 }
48
49 #if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS
50 return "\\temp\\";
51 #elif GTEST_OS_LINUX_ANDROID
52 // Android applications are expected to call the framework's
53 // Context.getExternalStorageDirectory() method through JNI to get the
54 // location of the world-writable SD Card directory. However, this requires a
55 // Context handle, which cannot be retrieved globally from native code. Doing
56 // so also precludes running the code as part of a regular standalone
57 // executable, which doesn't run in a Dalvik process (e.g. when running it
58 // through 'adb shell').
59 //
60 // Starting from Android O, the recommended generic temporary directory is
61 // '/data/local/tmp'. The recommended fallback is the current directory,
62 // which is usually accessible in app context.
63 if (::access("/data/local/tmp", R_OK | W_OK | X_OK) == 0)
64 return "/data/local/tmp/";
65 const char* current_dir = ::getcwd(nullptr, 0);
66 if (current_dir != nullptr &&
67 ::access(current_dir, R_OK | W_OK | X_OK) == 0) {
68 temp_dir = current_dir;
69 temp_dir.push_back(GTEST_PATH_SEP_[0]);
70 return temp_dir;
71 }
72 // Before Android O, /sdcard is usually available.
73 if (::access("/sdcard", R_OK | W_OK | X_OK) == 0)
74 return "/sdcard/";
75 // Generic POSIX fallback.
76 return "/tmp/";
77 #elif GTEST_OS_IOS
78 char name_template[PATH_MAX + 1];
79
80 // Documented alternative to NSTemporaryDirectory() (for obtaining creating
81 // a temporary directory) at
82 // https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10
83 //
84 // _CS_DARWIN_USER_TEMP_DIR (as well as _CS_DARWIN_USER_CACHE_DIR) is not
85 // documented in the confstr() man page at
86 // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/confstr.3.html#//apple_ref/doc/man/3/confstr
87 // but are still available, according to the WebKit patches at
88 // https://trac.webkit.org/changeset/262004/webkit
89 // https://trac.webkit.org/changeset/263705/webkit
90 //
91 // The confstr() implementation falls back to getenv("TMPDIR"). See
92 // https://opensource.apple.com/source/Libc/Libc-1439.100.3/gen/confstr.c.auto.html
93 ::confstr(_CS_DARWIN_USER_TEMP_DIR, name_template, sizeof(name_template));
94
95 temp_dir = name_template;
96 if (temp_dir.back() != GTEST_PATH_SEP_[0])
97 temp_dir.push_back(GTEST_PATH_SEP_[0]);
98 return temp_dir;
99 #else
100 return "/tmp/";
101 #endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS
102 }
103
104 } // namespace testing
105