| /* |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "test/testsupport/file_utils.h" |
| |
| #if defined(WEBRTC_POSIX) |
| #include <unistd.h> |
| #endif |
| |
| #if defined(WEBRTC_WIN) |
| #include <direct.h> |
| #include <tchar.h> |
| #include <windows.h> |
| |
| #include <algorithm> |
| #include <locale> |
| |
| #include "Shlwapi.h" |
| #include "WinDef.h" |
| #include "rtc_base/win32.h" |
| |
| #define GET_CURRENT_DIR _getcwd |
| #else |
| #include <dirent.h> |
| |
| #define GET_CURRENT_DIR getcwd |
| #endif |
| |
| #include <sys/stat.h> // To check for directory existence. |
| #ifndef S_ISDIR // Not defined in stat.h on Windows. |
| #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) |
| #endif |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include <memory> |
| #include <type_traits> |
| #include <utility> |
| |
| #if defined(WEBRTC_IOS) |
| #include "test/testsupport/ios_file_utils.h" |
| #elif defined(WEBRTC_MAC) |
| #include "test/testsupport/mac_file_utils.h" |
| #endif |
| |
| #include "absl/strings/string_view.h" |
| #include "rtc_base/checks.h" |
| #include "rtc_base/crypto_random.h" |
| #include "rtc_base/string_utils.h" |
| #include "rtc_base/strings/string_builder.h" |
| #include "test/testsupport/file_utils_override.h" |
| |
| namespace webrtc { |
| namespace test { |
| |
| #if defined(WEBRTC_WIN) |
| ABSL_CONST_INIT const absl::string_view kPathDelimiter = "\\"; |
| #else |
| ABSL_CONST_INIT const absl::string_view kPathDelimiter = "/"; |
| #endif |
| |
| std::string DirName(absl::string_view path) { |
| if (path.empty()) |
| return ""; |
| if (path == kPathDelimiter) |
| return std::string(path); |
| |
| if (path.back() == kPathDelimiter[0]) |
| path.remove_suffix(1); // Remove trailing separator. |
| |
| return std::string(path.substr(0, path.find_last_of(kPathDelimiter))); |
| } |
| |
| bool FileExists(absl::string_view file_name) { |
| struct stat file_info = {0}; |
| return stat(std::string(file_name).c_str(), &file_info) == 0; |
| } |
| |
| bool DirExists(absl::string_view directory_name) { |
| struct stat directory_info = {0}; |
| return stat(std::string(directory_name).c_str(), &directory_info) == 0 && |
| S_ISDIR(directory_info.st_mode); |
| } |
| |
| std::string OutputPath() { |
| return webrtc::test::internal::OutputPath(); |
| } |
| |
| std::string OutputPathWithRandomDirectory() { |
| std::string path = webrtc::test::internal::OutputPath(); |
| std::string rand_dir = path + rtc::CreateRandomUuid(); |
| |
| return CreateDir(rand_dir) ? rand_dir + std::string(kPathDelimiter) : path; |
| } |
| |
| std::string WorkingDir() { |
| return webrtc::test::internal::WorkingDir(); |
| } |
| |
| // Generate a temporary filename in a safe way. |
| // Largely copied from talk/base/{unixfilesystem,win32filesystem}.cc. |
| std::string TempFilename(absl::string_view dir, absl::string_view prefix) { |
| #ifdef WIN32 |
| wchar_t filename[MAX_PATH]; |
| if (::GetTempFileNameW(rtc::ToUtf16(dir).c_str(), |
| rtc::ToUtf16(prefix).c_str(), 0, filename) != 0) |
| return rtc::ToUtf8(filename); |
| RTC_DCHECK_NOTREACHED(); |
| return ""; |
| #else |
| rtc::StringBuilder os; |
| os << dir << "/" << prefix << "XXXXXX"; |
| std::string tempname = os.Release(); |
| |
| int fd = ::mkstemp(tempname.data()); |
| if (fd == -1) { |
| RTC_DCHECK_NOTREACHED(); |
| return ""; |
| } else { |
| ::close(fd); |
| } |
| return tempname; |
| #endif |
| } |
| |
| std::string GenerateTempFilename(absl::string_view dir, |
| absl::string_view prefix) { |
| std::string filename = TempFilename(dir, prefix); |
| RemoveFile(filename); |
| return filename; |
| } |
| |
| std::optional<std::vector<std::string>> ReadDirectory(absl::string_view path) { |
| if (path.length() == 0) |
| return std::optional<std::vector<std::string>>(); |
| |
| std::string path_str(path); |
| |
| #if defined(WEBRTC_WIN) |
| // Append separator character if needed. |
| if (path_str.back() != '\\') |
| path_str += '\\'; |
| |
| // Init. |
| WIN32_FIND_DATAW data; |
| HANDLE handle = ::FindFirstFileW(rtc::ToUtf16(path_str + '*').c_str(), &data); |
| if (handle == INVALID_HANDLE_VALUE) |
| return std::optional<std::vector<std::string>>(); |
| |
| // Populate output. |
| std::vector<std::string> found_entries; |
| do { |
| const std::string name = rtc::ToUtf8(data.cFileName); |
| if (name != "." && name != "..") |
| found_entries.emplace_back(path_str + name); |
| } while (::FindNextFileW(handle, &data) == TRUE); |
| |
| // Release resources. |
| if (handle != INVALID_HANDLE_VALUE) |
| ::FindClose(handle); |
| #else |
| // Append separator character if needed. |
| if (path_str.back() != '/') |
| path_str += '/'; |
| |
| // Init. |
| DIR* dir = ::opendir(path_str.c_str()); |
| if (dir == nullptr) |
| return std::optional<std::vector<std::string>>(); |
| |
| // Populate output. |
| std::vector<std::string> found_entries; |
| while (dirent* dirent = readdir(dir)) { |
| const std::string& name = dirent->d_name; |
| if (name != "." && name != "..") |
| found_entries.emplace_back(path_str + name); |
| } |
| |
| // Release resources. |
| closedir(dir); |
| #endif |
| |
| return std::optional<std::vector<std::string>>(std::move(found_entries)); |
| } |
| |
| bool CreateDir(absl::string_view directory_name) { |
| std::string directory_name_str(directory_name); |
| struct stat path_info = {0}; |
| // Check if the path exists already: |
| if (stat(directory_name_str.c_str(), &path_info) == 0) { |
| if (!S_ISDIR(path_info.st_mode)) { |
| fprintf(stderr, |
| "Path %s exists but is not a directory! Remove this " |
| "file and re-run to create the directory.\n", |
| directory_name_str.c_str()); |
| return false; |
| } |
| } else { |
| #ifdef WIN32 |
| return _mkdir(directory_name_str.c_str()) == 0; |
| #else |
| return mkdir(directory_name_str.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0; |
| #endif |
| } |
| return true; |
| } |
| |
| bool RemoveDir(absl::string_view directory_name) { |
| #ifdef WIN32 |
| return RemoveDirectoryA(std::string(directory_name).c_str()) != FALSE; |
| #else |
| return rmdir(std::string(directory_name).c_str()) == 0; |
| #endif |
| } |
| |
| bool RemoveFile(absl::string_view file_name) { |
| #ifdef WIN32 |
| return DeleteFileA(std::string(file_name).c_str()) != FALSE; |
| #else |
| return unlink(std::string(file_name).c_str()) == 0; |
| #endif |
| } |
| |
| std::string ResourcePath(absl::string_view name, absl::string_view extension) { |
| return webrtc::test::internal::ResourcePath(name, extension); |
| } |
| |
| std::string JoinFilename(absl::string_view dir, absl::string_view name) { |
| RTC_CHECK(!dir.empty()) << "Special cases not implemented."; |
| rtc::StringBuilder os; |
| os << dir; |
| // If the directory path already ends with a path delimiter don't append it |
| if (dir.back() != kPathDelimiter.back()) { |
| os << kPathDelimiter; |
| } |
| os << name; |
| return os.Release(); |
| } |
| |
| size_t GetFileSize(absl::string_view filename) { |
| FILE* f = fopen(std::string(filename).c_str(), "rb"); |
| size_t size = 0; |
| if (f != NULL) { |
| if (fseek(f, 0, SEEK_END) == 0) { |
| size = ftell(f); |
| } |
| fclose(f); |
| } |
| return size; |
| } |
| |
| } // namespace test |
| } // namespace webrtc |