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