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