1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "android-base/logging.h"
18 #include "android-base/test_utils.h"
19 #include "utils/Compat.h" // For OS_PATH_SEPARATOR.
20
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #if defined(_WIN32)
28 #include <windows.h>
29 #include <direct.h>
30 #endif
31
32 #include <string>
33
34 #ifdef _WIN32
mkstemp(char * template_name)35 int mkstemp(char* template_name) {
36 if (_mktemp(template_name) == nullptr) {
37 return -1;
38 }
39 // Use open() to match the close() that TemporaryFile's destructor does.
40 // Use O_BINARY to match base file APIs.
41 return open(template_name, O_CREAT | O_EXCL | O_RDWR | O_BINARY,
42 S_IRUSR | S_IWUSR);
43 }
44
mkdtemp(char * template_name)45 char* mkdtemp(char* template_name) {
46 if (_mktemp(template_name) == nullptr) {
47 return nullptr;
48 }
49 if (_mkdir(template_name) == -1) {
50 return nullptr;
51 }
52 return template_name;
53 }
54 #endif
55
GetSystemTempDir()56 static std::string GetSystemTempDir() {
57 #if defined(__ANDROID__)
58 return "/data/local/tmp";
59 #elif defined(_WIN32)
60 char tmp_dir[MAX_PATH];
61 DWORD result = GetTempPathA(sizeof(tmp_dir), tmp_dir);
62 CHECK_NE(result, 0ul) << "GetTempPathA failed, error: " << GetLastError();
63 CHECK_LT(result, sizeof(tmp_dir)) << "path truncated to: " << result;
64
65 // GetTempPath() returns a path with a trailing slash, but init()
66 // does not expect that, so remove it.
67 CHECK_EQ(tmp_dir[result - 1], '\\');
68 tmp_dir[result - 1] = '\0';
69 return tmp_dir;
70 #else
71 return "/tmp";
72 #endif
73 }
74
TemporaryFile()75 TemporaryFile::TemporaryFile() {
76 init(GetSystemTempDir());
77 }
78
~TemporaryFile()79 TemporaryFile::~TemporaryFile() {
80 close(fd);
81 unlink(path);
82 }
83
init(const std::string & tmp_dir)84 void TemporaryFile::init(const std::string& tmp_dir) {
85 snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(),
86 OS_PATH_SEPARATOR);
87 fd = mkstemp(path);
88 }
89
TemporaryDir()90 TemporaryDir::TemporaryDir() {
91 init(GetSystemTempDir());
92 }
93
~TemporaryDir()94 TemporaryDir::~TemporaryDir() {
95 rmdir(path);
96 }
97
init(const std::string & tmp_dir)98 bool TemporaryDir::init(const std::string& tmp_dir) {
99 snprintf(path, sizeof(path), "%s%cTemporaryDir-XXXXXX", tmp_dir.c_str(),
100 OS_PATH_SEPARATOR);
101 return (mkdtemp(path) != nullptr);
102 }
103