• 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 #include <assert.h>
14 
15 #if defined(WEBRTC_POSIX)
16 #include <unistd.h>
17 #endif
18 
19 #if defined(WEBRTC_WIN)
20 #include <direct.h>
21 #include <tchar.h>
22 #include <windows.h>
23 
24 #include <algorithm>
25 #include <codecvt>
26 #include <locale>
27 
28 #include "Shlwapi.h"
29 #include "WinDef.h"
30 #include "rtc_base/win32.h"
31 
32 #define GET_CURRENT_DIR _getcwd
33 #else
34 #include <dirent.h>
35 
36 #define GET_CURRENT_DIR getcwd
37 #endif
38 
39 #include <sys/stat.h>  // To check for directory existence.
40 #ifndef S_ISDIR        // Not defined in stat.h on Windows.
41 #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
42 #endif
43 
44 #include <stdio.h>
45 #include <stdlib.h>
46 
47 #include <memory>
48 #include <type_traits>
49 #include <utility>
50 
51 #if defined(WEBRTC_IOS)
52 #include "test/testsupport/ios_file_utils.h"
53 #elif defined(WEBRTC_MAC)
54 #include "test/testsupport/mac_file_utils.h"
55 #endif
56 
57 #include "rtc_base/checks.h"
58 #include "rtc_base/string_utils.h"
59 #include "test/testsupport/file_utils_override.h"
60 
61 namespace webrtc {
62 namespace test {
63 
64 #if defined(WEBRTC_WIN)
65 const char* kPathDelimiter = "\\";
66 #else
67 const char* kPathDelimiter = "/";
68 #endif
69 
DirName(const std::string & path)70 std::string DirName(const std::string& path) {
71   if (path.empty())
72     return "";
73   if (path == kPathDelimiter)
74     return path;
75 
76   std::string result = path;
77   if (result.back() == *kPathDelimiter)
78     result.pop_back();  // Remove trailing separator.
79 
80   return result.substr(0, result.find_last_of(kPathDelimiter));
81 }
82 
FileExists(const std::string & file_name)83 bool FileExists(const std::string& file_name) {
84   struct stat file_info = {0};
85   return stat(file_name.c_str(), &file_info) == 0;
86 }
87 
DirExists(const std::string & directory_name)88 bool DirExists(const std::string& directory_name) {
89   struct stat directory_info = {0};
90   return stat(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(const std::string & dir,const std::string & prefix)104 std::string TempFilename(const std::string& dir, const std::string& 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   assert(false);
111   return "";
112 #else
113   int len = dir.size() + prefix.size() + 2 + 6;
114   std::unique_ptr<char[]> tempname(new char[len]);
115 
116   snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(), prefix.c_str());
117   int fd = ::mkstemp(tempname.get());
118   if (fd == -1) {
119     assert(false);
120     return "";
121   } else {
122     ::close(fd);
123   }
124   std::string ret(tempname.get());
125   return ret;
126 #endif
127 }
128 
GenerateTempFilename(const std::string & dir,const std::string & prefix)129 std::string GenerateTempFilename(const std::string& dir,
130                                  const std::string& prefix) {
131   std::string filename = TempFilename(dir, prefix);
132   RemoveFile(filename);
133   return filename;
134 }
135 
ReadDirectory(std::string path)136 absl::optional<std::vector<std::string>> ReadDirectory(std::string path) {
137   if (path.length() == 0)
138     return absl::optional<std::vector<std::string>>();
139 
140 #if defined(WEBRTC_WIN)
141   // Append separator character if needed.
142   if (path.back() != '\\')
143     path += '\\';
144 
145   // Init.
146   WIN32_FIND_DATAW data;
147   HANDLE handle = ::FindFirstFileW(rtc::ToUtf16(path + '*').c_str(), &data);
148   if (handle == INVALID_HANDLE_VALUE)
149     return absl::optional<std::vector<std::string>>();
150 
151   // Populate output.
152   std::vector<std::string> found_entries;
153   do {
154     const std::string name = rtc::ToUtf8(data.cFileName);
155     if (name != "." && name != "..")
156       found_entries.emplace_back(path + name);
157   } while (::FindNextFileW(handle, &data) == TRUE);
158 
159   // Release resources.
160   if (handle != INVALID_HANDLE_VALUE)
161     ::FindClose(handle);
162 #else
163   // Append separator character if needed.
164   if (path.back() != '/')
165     path += '/';
166 
167   // Init.
168   DIR* dir = ::opendir(path.c_str());
169   if (dir == nullptr)
170     return absl::optional<std::vector<std::string>>();
171 
172   // Populate output.
173   std::vector<std::string> found_entries;
174   while (dirent* dirent = readdir(dir)) {
175     const std::string& name = dirent->d_name;
176     if (name != "." && name != "..")
177       found_entries.emplace_back(path + name);
178   }
179 
180   // Release resources.
181   closedir(dir);
182 #endif
183 
184   return absl::optional<std::vector<std::string>>(std::move(found_entries));
185 }
186 
CreateDir(const std::string & directory_name)187 bool CreateDir(const std::string& directory_name) {
188   struct stat path_info = {0};
189   // Check if the path exists already:
190   if (stat(directory_name.c_str(), &path_info) == 0) {
191     if (!S_ISDIR(path_info.st_mode)) {
192       fprintf(stderr,
193               "Path %s exists but is not a directory! Remove this "
194               "file and re-run to create the directory.\n",
195               directory_name.c_str());
196       return false;
197     }
198   } else {
199 #ifdef WIN32
200     return _mkdir(directory_name.c_str()) == 0;
201 #else
202     return mkdir(directory_name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0;
203 #endif
204   }
205   return true;
206 }
207 
RemoveDir(const std::string & directory_name)208 bool RemoveDir(const std::string& directory_name) {
209 #ifdef WIN32
210   return RemoveDirectoryA(directory_name.c_str()) != FALSE;
211 #else
212   return rmdir(directory_name.c_str()) == 0;
213 #endif
214 }
215 
RemoveFile(const std::string & file_name)216 bool RemoveFile(const std::string& file_name) {
217 #ifdef WIN32
218   return DeleteFileA(file_name.c_str()) != FALSE;
219 #else
220   return unlink(file_name.c_str()) == 0;
221 #endif
222 }
223 
ResourcePath(const std::string & name,const std::string & extension)224 std::string ResourcePath(const std::string& name,
225                          const std::string& extension) {
226   return webrtc::test::internal::ResourcePath(name, extension);
227 }
228 
JoinFilename(const std::string & dir,const std::string & name)229 std::string JoinFilename(const std::string& dir, const std::string& name) {
230   RTC_CHECK(!dir.empty()) << "Special cases not implemented.";
231   return dir + kPathDelimiter + name;
232 }
233 
GetFileSize(const std::string & filename)234 size_t GetFileSize(const std::string& filename) {
235   FILE* f = fopen(filename.c_str(), "rb");
236   size_t size = 0;
237   if (f != NULL) {
238     if (fseek(f, 0, SEEK_END) == 0) {
239       size = ftell(f);
240     }
241     fclose(f);
242   }
243   return size;
244 }
245 
246 }  // namespace test
247 }  // namespace webrtc
248