1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "test/testsupport/file_utils.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker
14*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_POSIX)
15*d9f75844SAndroid Build Coastguard Worker #include <unistd.h>
16*d9f75844SAndroid Build Coastguard Worker #endif
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_WIN)
19*d9f75844SAndroid Build Coastguard Worker #include <direct.h>
20*d9f75844SAndroid Build Coastguard Worker #include <tchar.h>
21*d9f75844SAndroid Build Coastguard Worker #include <windows.h>
22*d9f75844SAndroid Build Coastguard Worker
23*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
24*d9f75844SAndroid Build Coastguard Worker #include <codecvt>
25*d9f75844SAndroid Build Coastguard Worker #include <locale>
26*d9f75844SAndroid Build Coastguard Worker
27*d9f75844SAndroid Build Coastguard Worker #include "Shlwapi.h"
28*d9f75844SAndroid Build Coastguard Worker #include "WinDef.h"
29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/win32.h"
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker #define GET_CURRENT_DIR _getcwd
32*d9f75844SAndroid Build Coastguard Worker #else
33*d9f75844SAndroid Build Coastguard Worker #include <dirent.h>
34*d9f75844SAndroid Build Coastguard Worker
35*d9f75844SAndroid Build Coastguard Worker #define GET_CURRENT_DIR getcwd
36*d9f75844SAndroid Build Coastguard Worker #endif
37*d9f75844SAndroid Build Coastguard Worker
38*d9f75844SAndroid Build Coastguard Worker #include <sys/stat.h> // To check for directory existence.
39*d9f75844SAndroid Build Coastguard Worker #ifndef S_ISDIR // Not defined in stat.h on Windows.
40*d9f75844SAndroid Build Coastguard Worker #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
41*d9f75844SAndroid Build Coastguard Worker #endif
42*d9f75844SAndroid Build Coastguard Worker
43*d9f75844SAndroid Build Coastguard Worker #include <stdio.h>
44*d9f75844SAndroid Build Coastguard Worker #include <stdlib.h>
45*d9f75844SAndroid Build Coastguard Worker
46*d9f75844SAndroid Build Coastguard Worker #include <memory>
47*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
48*d9f75844SAndroid Build Coastguard Worker #include <utility>
49*d9f75844SAndroid Build Coastguard Worker
50*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_IOS)
51*d9f75844SAndroid Build Coastguard Worker #include "test/testsupport/ios_file_utils.h"
52*d9f75844SAndroid Build Coastguard Worker #elif defined(WEBRTC_MAC)
53*d9f75844SAndroid Build Coastguard Worker #include "test/testsupport/mac_file_utils.h"
54*d9f75844SAndroid Build Coastguard Worker #endif
55*d9f75844SAndroid Build Coastguard Worker
56*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
57*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
58*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_utils.h"
59*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
60*d9f75844SAndroid Build Coastguard Worker #include "test/testsupport/file_utils_override.h"
61*d9f75844SAndroid Build Coastguard Worker
62*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
63*d9f75844SAndroid Build Coastguard Worker namespace test {
64*d9f75844SAndroid Build Coastguard Worker
65*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_WIN)
66*d9f75844SAndroid Build Coastguard Worker ABSL_CONST_INIT const absl::string_view kPathDelimiter = "\\";
67*d9f75844SAndroid Build Coastguard Worker #else
68*d9f75844SAndroid Build Coastguard Worker ABSL_CONST_INIT const absl::string_view kPathDelimiter = "/";
69*d9f75844SAndroid Build Coastguard Worker #endif
70*d9f75844SAndroid Build Coastguard Worker
DirName(absl::string_view path)71*d9f75844SAndroid Build Coastguard Worker std::string DirName(absl::string_view path) {
72*d9f75844SAndroid Build Coastguard Worker if (path.empty())
73*d9f75844SAndroid Build Coastguard Worker return "";
74*d9f75844SAndroid Build Coastguard Worker if (path == kPathDelimiter)
75*d9f75844SAndroid Build Coastguard Worker return std::string(path);
76*d9f75844SAndroid Build Coastguard Worker
77*d9f75844SAndroid Build Coastguard Worker if (path.back() == kPathDelimiter[0])
78*d9f75844SAndroid Build Coastguard Worker path.remove_suffix(1); // Remove trailing separator.
79*d9f75844SAndroid Build Coastguard Worker
80*d9f75844SAndroid Build Coastguard Worker return std::string(path.substr(0, path.find_last_of(kPathDelimiter)));
81*d9f75844SAndroid Build Coastguard Worker }
82*d9f75844SAndroid Build Coastguard Worker
FileExists(absl::string_view file_name)83*d9f75844SAndroid Build Coastguard Worker bool FileExists(absl::string_view file_name) {
84*d9f75844SAndroid Build Coastguard Worker struct stat file_info = {0};
85*d9f75844SAndroid Build Coastguard Worker return stat(std::string(file_name).c_str(), &file_info) == 0;
86*d9f75844SAndroid Build Coastguard Worker }
87*d9f75844SAndroid Build Coastguard Worker
DirExists(absl::string_view directory_name)88*d9f75844SAndroid Build Coastguard Worker bool DirExists(absl::string_view directory_name) {
89*d9f75844SAndroid Build Coastguard Worker struct stat directory_info = {0};
90*d9f75844SAndroid Build Coastguard Worker return stat(std::string(directory_name).c_str(), &directory_info) == 0 &&
91*d9f75844SAndroid Build Coastguard Worker S_ISDIR(directory_info.st_mode);
92*d9f75844SAndroid Build Coastguard Worker }
93*d9f75844SAndroid Build Coastguard Worker
OutputPath()94*d9f75844SAndroid Build Coastguard Worker std::string OutputPath() {
95*d9f75844SAndroid Build Coastguard Worker return webrtc::test::internal::OutputPath();
96*d9f75844SAndroid Build Coastguard Worker }
97*d9f75844SAndroid Build Coastguard Worker
WorkingDir()98*d9f75844SAndroid Build Coastguard Worker std::string WorkingDir() {
99*d9f75844SAndroid Build Coastguard Worker return webrtc::test::internal::WorkingDir();
100*d9f75844SAndroid Build Coastguard Worker }
101*d9f75844SAndroid Build Coastguard Worker
102*d9f75844SAndroid Build Coastguard Worker // Generate a temporary filename in a safe way.
103*d9f75844SAndroid Build Coastguard Worker // Largely copied from talk/base/{unixfilesystem,win32filesystem}.cc.
TempFilename(absl::string_view dir,absl::string_view prefix)104*d9f75844SAndroid Build Coastguard Worker std::string TempFilename(absl::string_view dir, absl::string_view prefix) {
105*d9f75844SAndroid Build Coastguard Worker #ifdef WIN32
106*d9f75844SAndroid Build Coastguard Worker wchar_t filename[MAX_PATH];
107*d9f75844SAndroid Build Coastguard Worker if (::GetTempFileNameW(rtc::ToUtf16(dir).c_str(),
108*d9f75844SAndroid Build Coastguard Worker rtc::ToUtf16(prefix).c_str(), 0, filename) != 0)
109*d9f75844SAndroid Build Coastguard Worker return rtc::ToUtf8(filename);
110*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
111*d9f75844SAndroid Build Coastguard Worker return "";
112*d9f75844SAndroid Build Coastguard Worker #else
113*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder os;
114*d9f75844SAndroid Build Coastguard Worker os << dir << "/" << prefix << "XXXXXX";
115*d9f75844SAndroid Build Coastguard Worker std::string tempname = os.Release();
116*d9f75844SAndroid Build Coastguard Worker
117*d9f75844SAndroid Build Coastguard Worker int fd = ::mkstemp(tempname.data());
118*d9f75844SAndroid Build Coastguard Worker if (fd == -1) {
119*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
120*d9f75844SAndroid Build Coastguard Worker return "";
121*d9f75844SAndroid Build Coastguard Worker } else {
122*d9f75844SAndroid Build Coastguard Worker ::close(fd);
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker return tempname;
125*d9f75844SAndroid Build Coastguard Worker #endif
126*d9f75844SAndroid Build Coastguard Worker }
127*d9f75844SAndroid Build Coastguard Worker
GenerateTempFilename(absl::string_view dir,absl::string_view prefix)128*d9f75844SAndroid Build Coastguard Worker std::string GenerateTempFilename(absl::string_view dir,
129*d9f75844SAndroid Build Coastguard Worker absl::string_view prefix) {
130*d9f75844SAndroid Build Coastguard Worker std::string filename = TempFilename(dir, prefix);
131*d9f75844SAndroid Build Coastguard Worker RemoveFile(filename);
132*d9f75844SAndroid Build Coastguard Worker return filename;
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker
ReadDirectory(absl::string_view path)135*d9f75844SAndroid Build Coastguard Worker absl::optional<std::vector<std::string>> ReadDirectory(absl::string_view path) {
136*d9f75844SAndroid Build Coastguard Worker if (path.length() == 0)
137*d9f75844SAndroid Build Coastguard Worker return absl::optional<std::vector<std::string>>();
138*d9f75844SAndroid Build Coastguard Worker
139*d9f75844SAndroid Build Coastguard Worker std::string path_str(path);
140*d9f75844SAndroid Build Coastguard Worker
141*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_WIN)
142*d9f75844SAndroid Build Coastguard Worker // Append separator character if needed.
143*d9f75844SAndroid Build Coastguard Worker if (path_str.back() != '\\')
144*d9f75844SAndroid Build Coastguard Worker path_str += '\\';
145*d9f75844SAndroid Build Coastguard Worker
146*d9f75844SAndroid Build Coastguard Worker // Init.
147*d9f75844SAndroid Build Coastguard Worker WIN32_FIND_DATAW data;
148*d9f75844SAndroid Build Coastguard Worker HANDLE handle = ::FindFirstFileW(rtc::ToUtf16(path_str + '*').c_str(), &data);
149*d9f75844SAndroid Build Coastguard Worker if (handle == INVALID_HANDLE_VALUE)
150*d9f75844SAndroid Build Coastguard Worker return absl::optional<std::vector<std::string>>();
151*d9f75844SAndroid Build Coastguard Worker
152*d9f75844SAndroid Build Coastguard Worker // Populate output.
153*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> found_entries;
154*d9f75844SAndroid Build Coastguard Worker do {
155*d9f75844SAndroid Build Coastguard Worker const std::string name = rtc::ToUtf8(data.cFileName);
156*d9f75844SAndroid Build Coastguard Worker if (name != "." && name != "..")
157*d9f75844SAndroid Build Coastguard Worker found_entries.emplace_back(path_str + name);
158*d9f75844SAndroid Build Coastguard Worker } while (::FindNextFileW(handle, &data) == TRUE);
159*d9f75844SAndroid Build Coastguard Worker
160*d9f75844SAndroid Build Coastguard Worker // Release resources.
161*d9f75844SAndroid Build Coastguard Worker if (handle != INVALID_HANDLE_VALUE)
162*d9f75844SAndroid Build Coastguard Worker ::FindClose(handle);
163*d9f75844SAndroid Build Coastguard Worker #else
164*d9f75844SAndroid Build Coastguard Worker // Append separator character if needed.
165*d9f75844SAndroid Build Coastguard Worker if (path_str.back() != '/')
166*d9f75844SAndroid Build Coastguard Worker path_str += '/';
167*d9f75844SAndroid Build Coastguard Worker
168*d9f75844SAndroid Build Coastguard Worker // Init.
169*d9f75844SAndroid Build Coastguard Worker DIR* dir = ::opendir(path_str.c_str());
170*d9f75844SAndroid Build Coastguard Worker if (dir == nullptr)
171*d9f75844SAndroid Build Coastguard Worker return absl::optional<std::vector<std::string>>();
172*d9f75844SAndroid Build Coastguard Worker
173*d9f75844SAndroid Build Coastguard Worker // Populate output.
174*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> found_entries;
175*d9f75844SAndroid Build Coastguard Worker while (dirent* dirent = readdir(dir)) {
176*d9f75844SAndroid Build Coastguard Worker const std::string& name = dirent->d_name;
177*d9f75844SAndroid Build Coastguard Worker if (name != "." && name != "..")
178*d9f75844SAndroid Build Coastguard Worker found_entries.emplace_back(path_str + name);
179*d9f75844SAndroid Build Coastguard Worker }
180*d9f75844SAndroid Build Coastguard Worker
181*d9f75844SAndroid Build Coastguard Worker // Release resources.
182*d9f75844SAndroid Build Coastguard Worker closedir(dir);
183*d9f75844SAndroid Build Coastguard Worker #endif
184*d9f75844SAndroid Build Coastguard Worker
185*d9f75844SAndroid Build Coastguard Worker return absl::optional<std::vector<std::string>>(std::move(found_entries));
186*d9f75844SAndroid Build Coastguard Worker }
187*d9f75844SAndroid Build Coastguard Worker
CreateDir(absl::string_view directory_name)188*d9f75844SAndroid Build Coastguard Worker bool CreateDir(absl::string_view directory_name) {
189*d9f75844SAndroid Build Coastguard Worker std::string directory_name_str(directory_name);
190*d9f75844SAndroid Build Coastguard Worker struct stat path_info = {0};
191*d9f75844SAndroid Build Coastguard Worker // Check if the path exists already:
192*d9f75844SAndroid Build Coastguard Worker if (stat(directory_name_str.c_str(), &path_info) == 0) {
193*d9f75844SAndroid Build Coastguard Worker if (!S_ISDIR(path_info.st_mode)) {
194*d9f75844SAndroid Build Coastguard Worker fprintf(stderr,
195*d9f75844SAndroid Build Coastguard Worker "Path %s exists but is not a directory! Remove this "
196*d9f75844SAndroid Build Coastguard Worker "file and re-run to create the directory.\n",
197*d9f75844SAndroid Build Coastguard Worker directory_name_str.c_str());
198*d9f75844SAndroid Build Coastguard Worker return false;
199*d9f75844SAndroid Build Coastguard Worker }
200*d9f75844SAndroid Build Coastguard Worker } else {
201*d9f75844SAndroid Build Coastguard Worker #ifdef WIN32
202*d9f75844SAndroid Build Coastguard Worker return _mkdir(directory_name_str.c_str()) == 0;
203*d9f75844SAndroid Build Coastguard Worker #else
204*d9f75844SAndroid Build Coastguard Worker return mkdir(directory_name_str.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0;
205*d9f75844SAndroid Build Coastguard Worker #endif
206*d9f75844SAndroid Build Coastguard Worker }
207*d9f75844SAndroid Build Coastguard Worker return true;
208*d9f75844SAndroid Build Coastguard Worker }
209*d9f75844SAndroid Build Coastguard Worker
RemoveDir(absl::string_view directory_name)210*d9f75844SAndroid Build Coastguard Worker bool RemoveDir(absl::string_view directory_name) {
211*d9f75844SAndroid Build Coastguard Worker #ifdef WIN32
212*d9f75844SAndroid Build Coastguard Worker return RemoveDirectoryA(std::string(directory_name).c_str()) != FALSE;
213*d9f75844SAndroid Build Coastguard Worker #else
214*d9f75844SAndroid Build Coastguard Worker return rmdir(std::string(directory_name).c_str()) == 0;
215*d9f75844SAndroid Build Coastguard Worker #endif
216*d9f75844SAndroid Build Coastguard Worker }
217*d9f75844SAndroid Build Coastguard Worker
RemoveFile(absl::string_view file_name)218*d9f75844SAndroid Build Coastguard Worker bool RemoveFile(absl::string_view file_name) {
219*d9f75844SAndroid Build Coastguard Worker #ifdef WIN32
220*d9f75844SAndroid Build Coastguard Worker return DeleteFileA(std::string(file_name).c_str()) != FALSE;
221*d9f75844SAndroid Build Coastguard Worker #else
222*d9f75844SAndroid Build Coastguard Worker return unlink(std::string(file_name).c_str()) == 0;
223*d9f75844SAndroid Build Coastguard Worker #endif
224*d9f75844SAndroid Build Coastguard Worker }
225*d9f75844SAndroid Build Coastguard Worker
ResourcePath(absl::string_view name,absl::string_view extension)226*d9f75844SAndroid Build Coastguard Worker std::string ResourcePath(absl::string_view name, absl::string_view extension) {
227*d9f75844SAndroid Build Coastguard Worker return webrtc::test::internal::ResourcePath(name, extension);
228*d9f75844SAndroid Build Coastguard Worker }
229*d9f75844SAndroid Build Coastguard Worker
JoinFilename(absl::string_view dir,absl::string_view name)230*d9f75844SAndroid Build Coastguard Worker std::string JoinFilename(absl::string_view dir, absl::string_view name) {
231*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(!dir.empty()) << "Special cases not implemented.";
232*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder os;
233*d9f75844SAndroid Build Coastguard Worker os << dir << kPathDelimiter << name;
234*d9f75844SAndroid Build Coastguard Worker return os.Release();
235*d9f75844SAndroid Build Coastguard Worker }
236*d9f75844SAndroid Build Coastguard Worker
GetFileSize(absl::string_view filename)237*d9f75844SAndroid Build Coastguard Worker size_t GetFileSize(absl::string_view filename) {
238*d9f75844SAndroid Build Coastguard Worker FILE* f = fopen(std::string(filename).c_str(), "rb");
239*d9f75844SAndroid Build Coastguard Worker size_t size = 0;
240*d9f75844SAndroid Build Coastguard Worker if (f != NULL) {
241*d9f75844SAndroid Build Coastguard Worker if (fseek(f, 0, SEEK_END) == 0) {
242*d9f75844SAndroid Build Coastguard Worker size = ftell(f);
243*d9f75844SAndroid Build Coastguard Worker }
244*d9f75844SAndroid Build Coastguard Worker fclose(f);
245*d9f75844SAndroid Build Coastguard Worker }
246*d9f75844SAndroid Build Coastguard Worker return size;
247*d9f75844SAndroid Build Coastguard Worker }
248*d9f75844SAndroid Build Coastguard Worker
249*d9f75844SAndroid Build Coastguard Worker } // namespace test
250*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
251