blob: 96bd4954bffe107a5e584b58e232df82622c2890 [file] [log] [blame]
kjellander@webrtc.org7951e812011-10-13 12:24:41 +00001/*
andrew@webrtc.org7a281a52012-06-27 03:22:37 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
kjellander@webrtc.org7951e812011-10-13 12:24:41 +00003 *
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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "test/testsupport/file_utils.h"
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000012
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000013#include <assert.h>
henrike@webrtc.orgf2aafe42014-04-29 17:54:17 +000014
Patrik Höglund8434aeb2018-10-05 14:52:11 +020015#if defined(WEBRTC_POSIX)
16#include <unistd.h>
17#endif
18
19#if defined(WEBRTC_WIN)
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000020#include <direct.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000021#include <tchar.h>
22#include <windows.h>
kjellander@webrtc.orgde499662013-08-29 11:26:41 +000023#include <algorithm>
Patrik Höglund8434aeb2018-10-05 14:52:11 +020024#include <codecvt>
25#include <locale>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000026
ehmaldonado00f2ee02016-11-18 07:06:41 -080027#include "Shlwapi.h"
ehmaldonado37535bf2016-12-05 06:42:45 -080028#include "WinDef.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020029#include "rtc_base/win32.h"
Yves Gerey3e707812018-11-28 16:47:49 +010030
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000031#define GET_CURRENT_DIR _getcwd
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000032#else
alessiob00b16f42017-06-01 03:29:40 -070033#include <dirent.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000034
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000035#define GET_CURRENT_DIR getcwd
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000036#endif
37
38#include <sys/stat.h> // To check for directory existence.
Yves Gerey665174f2018-06-19 15:03:05 +020039#ifndef S_ISDIR // Not defined in stat.h on Windows.
40#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000041#endif
42
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000043#include <stdio.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000044#include <stdlib.h>
kwibergbfefb032016-05-01 14:53:46 -070045#include <memory>
Yves Gerey3e707812018-11-28 16:47:49 +010046#include <type_traits>
alessiob00b16f42017-06-01 03:29:40 -070047#include <utility>
kwibergbfefb032016-05-01 14:53:46 -070048
Patrik Höglund8434aeb2018-10-05 14:52:11 +020049#if defined(WEBRTC_IOS)
Steve Anton10542f22019-01-11 09:11:00 -080050#include "test/testsupport/ios_file_utils.h"
Oleh Prypineec86cd2019-07-08 09:47:41 +020051#elif defined(WEBRTC_MAC)
Steve Anton10542f22019-01-11 09:11:00 -080052#include "test/testsupport/mac_file_utils.h"
Patrik Höglund8434aeb2018-10-05 14:52:11 +020053#endif
54
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020055#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080056#include "rtc_base/string_utils.h"
57#include "test/testsupport/file_utils_override.h"
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +000058
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000059namespace webrtc {
60namespace test {
61
Patrik Höglund8434aeb2018-10-05 14:52:11 +020062#if defined(WEBRTC_WIN)
henrike@webrtc.org34773d92013-07-08 14:55:23 +000063const char* kPathDelimiter = "\\";
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000064#else
henrike@webrtc.org34773d92013-07-08 14:55:23 +000065const char* kPathDelimiter = "/";
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000066#endif
leozwang@webrtc.org363efef2012-10-16 04:31:20 +000067
Patrik Höglund8434aeb2018-10-05 14:52:11 +020068std::string DirName(const std::string& path) {
69 if (path.empty())
70 return "";
71 if (path == kPathDelimiter)
72 return path;
73
74 std::string result = path;
75 if (result.back() == *kPathDelimiter)
76 result.pop_back(); // Remove trailing separator.
77
78 return result.substr(0, result.find_last_of(kPathDelimiter));
79}
80
ehmaldonado88df0bc2017-02-10 09:27:14 -080081bool FileExists(const std::string& file_name) {
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +000082 struct stat file_info = {0};
83 return stat(file_name.c_str(), &file_info) == 0;
84}
85
alessiobe49fede2017-03-15 06:04:59 -070086bool DirExists(const std::string& directory_name) {
87 struct stat directory_info = {0};
Yves Gerey665174f2018-06-19 15:03:05 +020088 return stat(directory_name.c_str(), &directory_info) == 0 &&
89 S_ISDIR(directory_info.st_mode);
alessiobe49fede2017-03-15 06:04:59 -070090}
91
andrew@webrtc.org0db7dc62011-11-13 01:34:05 +000092std::string OutputPath() {
Artem Titov8f726be2018-10-23 15:50:10 +020093 return webrtc::test::internal::OutputPath();
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000094}
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +000095
96std::string WorkingDir() {
Artem Titov8f726be2018-10-23 15:50:10 +020097 return webrtc::test::internal::WorkingDir();
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +000098}
99
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000100// Generate a temporary filename in a safe way.
101// Largely copied from talk/base/{unixfilesystem,win32filesystem}.cc.
Yves Gerey665174f2018-06-19 15:03:05 +0200102std::string TempFilename(const std::string& dir, const std::string& prefix) {
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000103#ifdef WIN32
104 wchar_t filename[MAX_PATH];
Mirko Bonadei673f7e52019-03-25 09:01:02 +0100105 if (::GetTempFileNameW(rtc::ToUtf16(dir).c_str(),
106 rtc::ToUtf16(prefix).c_str(), 0, filename) != 0)
nisse07b83882017-03-14 01:32:50 -0700107 return rtc::ToUtf8(filename);
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000108 assert(false);
109 return "";
110#else
111 int len = dir.size() + prefix.size() + 2 + 6;
kwibergbfefb032016-05-01 14:53:46 -0700112 std::unique_ptr<char[]> tempname(new char[len]);
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000113
Yves Gerey665174f2018-06-19 15:03:05 +0200114 snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(), prefix.c_str());
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000115 int fd = ::mkstemp(tempname.get());
116 if (fd == -1) {
117 assert(false);
118 return "";
119 } else {
120 ::close(fd);
121 }
122 std::string ret(tempname.get());
123 return ret;
124#endif
125}
126
Artem Titove62f6002018-03-19 15:40:00 +0100127std::string GenerateTempFilename(const std::string& dir,
128 const std::string& prefix) {
129 std::string filename = TempFilename(dir, prefix);
130 RemoveFile(filename);
131 return filename;
132}
133
Danil Chapovalov431abd92018-06-18 12:54:17 +0200134absl::optional<std::vector<std::string>> ReadDirectory(std::string path) {
alessiob00b16f42017-06-01 03:29:40 -0700135 if (path.length() == 0)
Danil Chapovalov431abd92018-06-18 12:54:17 +0200136 return absl::optional<std::vector<std::string>>();
alessiob00b16f42017-06-01 03:29:40 -0700137
138#if defined(WEBRTC_WIN)
139 // Append separator character if needed.
140 if (path.back() != '\\')
141 path += '\\';
142
143 // Init.
Mirko Bonadei673f7e52019-03-25 09:01:02 +0100144 WIN32_FIND_DATAW data;
145 HANDLE handle = ::FindFirstFileW(rtc::ToUtf16(path + '*').c_str(), &data);
alessiob00b16f42017-06-01 03:29:40 -0700146 if (handle == INVALID_HANDLE_VALUE)
Danil Chapovalov431abd92018-06-18 12:54:17 +0200147 return absl::optional<std::vector<std::string>>();
alessiob00b16f42017-06-01 03:29:40 -0700148
149 // Populate output.
150 std::vector<std::string> found_entries;
151 do {
152 const std::string name = rtc::ToUtf8(data.cFileName);
153 if (name != "." && name != "..")
154 found_entries.emplace_back(path + name);
Mirko Bonadei673f7e52019-03-25 09:01:02 +0100155 } while (::FindNextFileW(handle, &data) == TRUE);
alessiob00b16f42017-06-01 03:29:40 -0700156
157 // Release resources.
158 if (handle != INVALID_HANDLE_VALUE)
159 ::FindClose(handle);
160#else
161 // Append separator character if needed.
162 if (path.back() != '/')
163 path += '/';
164
165 // Init.
166 DIR* dir = ::opendir(path.c_str());
167 if (dir == nullptr)
Danil Chapovalov431abd92018-06-18 12:54:17 +0200168 return absl::optional<std::vector<std::string>>();
alessiob00b16f42017-06-01 03:29:40 -0700169
170 // Populate output.
171 std::vector<std::string> found_entries;
172 while (dirent* dirent = readdir(dir)) {
173 const std::string& name = dirent->d_name;
174 if (name != "." && name != "..")
175 found_entries.emplace_back(path + name);
176 }
177
178 // Release resources.
179 closedir(dir);
180#endif
181
Danil Chapovalov431abd92018-06-18 12:54:17 +0200182 return absl::optional<std::vector<std::string>>(std::move(found_entries));
alessiob00b16f42017-06-01 03:29:40 -0700183}
184
ehmaldonado88df0bc2017-02-10 09:27:14 -0800185bool CreateDir(const std::string& directory_name) {
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000186 struct stat path_info = {0};
187 // Check if the path exists already:
188 if (stat(directory_name.c_str(), &path_info) == 0) {
189 if (!S_ISDIR(path_info.st_mode)) {
Yves Gerey665174f2018-06-19 15:03:05 +0200190 fprintf(stderr,
191 "Path %s exists but is not a directory! Remove this "
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000192 "file and re-run to create the directory.\n",
193 directory_name.c_str());
194 return false;
195 }
196 } else {
197#ifdef WIN32
198 return _mkdir(directory_name.c_str()) == 0;
199#else
Yves Gerey665174f2018-06-19 15:03:05 +0200200 return mkdir(directory_name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0;
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000201#endif
202 }
203 return true;
204}
205
nisse57efb032017-05-18 03:55:59 -0700206bool RemoveDir(const std::string& directory_name) {
207#ifdef WIN32
Yves Gerey665174f2018-06-19 15:03:05 +0200208 return RemoveDirectoryA(directory_name.c_str()) != FALSE;
nisse57efb032017-05-18 03:55:59 -0700209#else
Yves Gerey665174f2018-06-19 15:03:05 +0200210 return rmdir(directory_name.c_str()) == 0;
nisse57efb032017-05-18 03:55:59 -0700211#endif
212}
213
214bool RemoveFile(const std::string& file_name) {
215#ifdef WIN32
216 return DeleteFileA(file_name.c_str()) != FALSE;
217#else
218 return unlink(file_name.c_str()) == 0;
219#endif
220}
221
ehmaldonado88df0bc2017-02-10 09:27:14 -0800222std::string ResourcePath(const std::string& name,
223 const std::string& extension) {
Artem Titov8f726be2018-10-23 15:50:10 +0200224 return webrtc::test::internal::ResourcePath(name, extension);
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000225}
226
Niels Möller392f8d02018-06-01 10:14:44 +0200227std::string JoinFilename(const std::string& dir, const std::string& name) {
228 RTC_CHECK(!dir.empty()) << "Special cases not implemented.";
229 return dir + kPathDelimiter + name;
230}
231
ehmaldonado88df0bc2017-02-10 09:27:14 -0800232size_t GetFileSize(const std::string& filename) {
kjellander@webrtc.org5b97b122011-12-08 07:42:18 +0000233 FILE* f = fopen(filename.c_str(), "rb");
234 size_t size = 0;
235 if (f != NULL) {
236 if (fseek(f, 0, SEEK_END) == 0) {
237 size = ftell(f);
238 }
239 fclose(f);
240 }
241 return size;
242}
243
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000244} // namespace test
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +0000245} // namespace webrtc