blob: 0b4ffa446c0881e4be022d4b89e21208c165d03d [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>
Jonas Olssona4d87372019-07-05 19:08:33 +020023
kjellander@webrtc.orgde499662013-08-29 11:26:41 +000024#include <algorithm>
Patrik Höglund8434aeb2018-10-05 14:52:11 +020025#include <codecvt>
26#include <locale>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000027
ehmaldonado00f2ee02016-11-18 07:06:41 -080028#include "Shlwapi.h"
ehmaldonado37535bf2016-12-05 06:42:45 -080029#include "WinDef.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "rtc_base/win32.h"
Yves Gerey3e707812018-11-28 16:47:49 +010031
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000032#define GET_CURRENT_DIR _getcwd
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000033#else
alessiob00b16f42017-06-01 03:29:40 -070034#include <dirent.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000035
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000036#define GET_CURRENT_DIR getcwd
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000037#endif
38
39#include <sys/stat.h> // To check for directory existence.
Yves Gerey665174f2018-06-19 15:03:05 +020040#ifndef S_ISDIR // Not defined in stat.h on Windows.
41#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000042#endif
43
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000044#include <stdio.h>
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +000045#include <stdlib.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020046
kwibergbfefb032016-05-01 14:53:46 -070047#include <memory>
Yves Gerey3e707812018-11-28 16:47:49 +010048#include <type_traits>
alessiob00b16f42017-06-01 03:29:40 -070049#include <utility>
kwibergbfefb032016-05-01 14:53:46 -070050
Patrik Höglund8434aeb2018-10-05 14:52:11 +020051#if defined(WEBRTC_IOS)
Steve Anton10542f22019-01-11 09:11:00 -080052#include "test/testsupport/ios_file_utils.h"
Oleh Prypineec86cd2019-07-08 09:47:41 +020053#elif defined(WEBRTC_MAC)
Steve Anton10542f22019-01-11 09:11:00 -080054#include "test/testsupport/mac_file_utils.h"
Patrik Höglund8434aeb2018-10-05 14:52:11 +020055#endif
56
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020057#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080058#include "rtc_base/string_utils.h"
59#include "test/testsupport/file_utils_override.h"
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +000060
kjellander@webrtc.org7951e812011-10-13 12:24:41 +000061namespace webrtc {
62namespace test {
63
Patrik Höglund8434aeb2018-10-05 14:52:11 +020064#if defined(WEBRTC_WIN)
henrike@webrtc.org34773d92013-07-08 14:55:23 +000065const char* kPathDelimiter = "\\";
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000066#else
henrike@webrtc.org34773d92013-07-08 14:55:23 +000067const char* kPathDelimiter = "/";
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000068#endif
leozwang@webrtc.org363efef2012-10-16 04:31:20 +000069
Patrik Höglund8434aeb2018-10-05 14:52:11 +020070std::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
ehmaldonado88df0bc2017-02-10 09:27:14 -080083bool FileExists(const std::string& file_name) {
kjellander@webrtc.org83b767b2012-10-15 18:14:12 +000084 struct stat file_info = {0};
85 return stat(file_name.c_str(), &file_info) == 0;
86}
87
alessiobe49fede2017-03-15 06:04:59 -070088bool DirExists(const std::string& directory_name) {
89 struct stat directory_info = {0};
Yves Gerey665174f2018-06-19 15:03:05 +020090 return stat(directory_name.c_str(), &directory_info) == 0 &&
91 S_ISDIR(directory_info.st_mode);
alessiobe49fede2017-03-15 06:04:59 -070092}
93
andrew@webrtc.org0db7dc62011-11-13 01:34:05 +000094std::string OutputPath() {
Artem Titov8f726be2018-10-23 15:50:10 +020095 return webrtc::test::internal::OutputPath();
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +000096}
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +000097
98std::string WorkingDir() {
Artem Titov8f726be2018-10-23 15:50:10 +020099 return webrtc::test::internal::WorkingDir();
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000100}
101
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000102// Generate a temporary filename in a safe way.
103// Largely copied from talk/base/{unixfilesystem,win32filesystem}.cc.
Yves Gerey665174f2018-06-19 15:03:05 +0200104std::string TempFilename(const std::string& dir, const std::string& prefix) {
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000105#ifdef WIN32
106 wchar_t filename[MAX_PATH];
Mirko Bonadei673f7e52019-03-25 09:01:02 +0100107 if (::GetTempFileNameW(rtc::ToUtf16(dir).c_str(),
108 rtc::ToUtf16(prefix).c_str(), 0, filename) != 0)
nisse07b83882017-03-14 01:32:50 -0700109 return rtc::ToUtf8(filename);
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000110 assert(false);
111 return "";
112#else
113 int len = dir.size() + prefix.size() + 2 + 6;
kwibergbfefb032016-05-01 14:53:46 -0700114 std::unique_ptr<char[]> tempname(new char[len]);
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000115
Yves Gerey665174f2018-06-19 15:03:05 +0200116 snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(), prefix.c_str());
kjellander@webrtc.org7de47bc2014-04-16 08:04:26 +0000117 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
Artem Titove62f6002018-03-19 15:40:00 +0100129std::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
Danil Chapovalov431abd92018-06-18 12:54:17 +0200136absl::optional<std::vector<std::string>> ReadDirectory(std::string path) {
alessiob00b16f42017-06-01 03:29:40 -0700137 if (path.length() == 0)
Danil Chapovalov431abd92018-06-18 12:54:17 +0200138 return absl::optional<std::vector<std::string>>();
alessiob00b16f42017-06-01 03:29:40 -0700139
140#if defined(WEBRTC_WIN)
141 // Append separator character if needed.
142 if (path.back() != '\\')
143 path += '\\';
144
145 // Init.
Mirko Bonadei673f7e52019-03-25 09:01:02 +0100146 WIN32_FIND_DATAW data;
147 HANDLE handle = ::FindFirstFileW(rtc::ToUtf16(path + '*').c_str(), &data);
alessiob00b16f42017-06-01 03:29:40 -0700148 if (handle == INVALID_HANDLE_VALUE)
Danil Chapovalov431abd92018-06-18 12:54:17 +0200149 return absl::optional<std::vector<std::string>>();
alessiob00b16f42017-06-01 03:29:40 -0700150
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);
Mirko Bonadei673f7e52019-03-25 09:01:02 +0100157 } while (::FindNextFileW(handle, &data) == TRUE);
alessiob00b16f42017-06-01 03:29:40 -0700158
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)
Danil Chapovalov431abd92018-06-18 12:54:17 +0200170 return absl::optional<std::vector<std::string>>();
alessiob00b16f42017-06-01 03:29:40 -0700171
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
Danil Chapovalov431abd92018-06-18 12:54:17 +0200184 return absl::optional<std::vector<std::string>>(std::move(found_entries));
alessiob00b16f42017-06-01 03:29:40 -0700185}
186
ehmaldonado88df0bc2017-02-10 09:27:14 -0800187bool CreateDir(const std::string& directory_name) {
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000188 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)) {
Yves Gerey665174f2018-06-19 15:03:05 +0200192 fprintf(stderr,
193 "Path %s exists but is not a directory! Remove this "
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000194 "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
Yves Gerey665174f2018-06-19 15:03:05 +0200202 return mkdir(directory_name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0;
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000203#endif
204 }
205 return true;
206}
207
nisse57efb032017-05-18 03:55:59 -0700208bool RemoveDir(const std::string& directory_name) {
209#ifdef WIN32
Yves Gerey665174f2018-06-19 15:03:05 +0200210 return RemoveDirectoryA(directory_name.c_str()) != FALSE;
nisse57efb032017-05-18 03:55:59 -0700211#else
Yves Gerey665174f2018-06-19 15:03:05 +0200212 return rmdir(directory_name.c_str()) == 0;
nisse57efb032017-05-18 03:55:59 -0700213#endif
214}
215
216bool 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
ehmaldonado88df0bc2017-02-10 09:27:14 -0800224std::string ResourcePath(const std::string& name,
225 const std::string& extension) {
Artem Titov8f726be2018-10-23 15:50:10 +0200226 return webrtc::test::internal::ResourcePath(name, extension);
kjellander@webrtc.org4ed4f242011-12-05 16:31:12 +0000227}
228
Niels Möller392f8d02018-06-01 10:14:44 +0200229std::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
ehmaldonado88df0bc2017-02-10 09:27:14 -0800234size_t GetFileSize(const std::string& filename) {
kjellander@webrtc.org5b97b122011-12-08 07:42:18 +0000235 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
kjellander@webrtc.org7951e812011-10-13 12:24:41 +0000246} // namespace test
kjellander@webrtc.org4d8cd9d2011-11-09 11:24:14 +0000247} // namespace webrtc