xref: /aosp_15_r20/external/webrtc/test/testsupport/file_utils.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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