| /* | |
| * 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/fileutils.h" | |
| #include <assert.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 <codecvt> | |
| #include <locale> | |
| #include "Shlwapi.h" | |
| #include "WinDef.h" | |
| #include "rtc_base/win32.h" | |
| #define GET_CURRENT_DIR _getcwd | |
| #else | |
| #include <dirent.h> | |
| #include <unistd.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 <string.h> | |
| #include <memory> | |
| #include <utility> | |
| #if defined(WEBRTC_IOS) | |
| #include "test/testsupport/iosfileutils.h" | |
| #endif | |
| #if defined(WEBRTC_MAC) | |
| #include "test/testsupport/macfileutils.h" | |
| #endif | |
| #include "rtc_base/arraysize.h" | |
| #include "rtc_base/checks.h" | |
| #include "rtc_base/stringutils.h" | |
| #include "test/testsupport/fileutils_override.h" | |
| namespace webrtc { | |
| namespace test { | |
| #if defined(WEBRTC_WIN) | |
| const char* kPathDelimiter = "\\"; | |
| #else | |
| const char* kPathDelimiter = "/"; | |
| #endif | |
| std::string DirName(const std::string& path) { | |
| if (path.empty()) | |
| return ""; | |
| if (path == kPathDelimiter) | |
| return path; | |
| std::string result = path; | |
| if (result.back() == *kPathDelimiter) | |
| result.pop_back(); // Remove trailing separator. | |
| return result.substr(0, result.find_last_of(kPathDelimiter)); | |
| } | |
| bool FileExists(const std::string& file_name) { | |
| struct stat file_info = {0}; | |
| return stat(file_name.c_str(), &file_info) == 0; | |
| } | |
| bool DirExists(const std::string& directory_name) { | |
| struct stat directory_info = {0}; | |
| return stat(directory_name.c_str(), &directory_info) == 0 && | |
| S_ISDIR(directory_info.st_mode); | |
| } | |
| std::string OutputPath() { | |
| return webrtc::test::internal::OutputPath(); | |
| } | |
| 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(const std::string& dir, const std::string& prefix) { | |
| #ifdef WIN32 | |
| wchar_t filename[MAX_PATH]; | |
| if (::GetTempFileName(rtc::ToUtf16(dir).c_str(), rtc::ToUtf16(prefix).c_str(), | |
| 0, filename) != 0) | |
| return rtc::ToUtf8(filename); | |
| assert(false); | |
| return ""; | |
| #else | |
| int len = dir.size() + prefix.size() + 2 + 6; | |
| std::unique_ptr<char[]> tempname(new char[len]); | |
| snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(), prefix.c_str()); | |
| int fd = ::mkstemp(tempname.get()); | |
| if (fd == -1) { | |
| assert(false); | |
| return ""; | |
| } else { | |
| ::close(fd); | |
| } | |
| std::string ret(tempname.get()); | |
| return ret; | |
| #endif | |
| } | |
| std::string GenerateTempFilename(const std::string& dir, | |
| const std::string& prefix) { | |
| std::string filename = TempFilename(dir, prefix); | |
| RemoveFile(filename); | |
| return filename; | |
| } | |
| absl::optional<std::vector<std::string>> ReadDirectory(std::string path) { | |
| if (path.length() == 0) | |
| return absl::optional<std::vector<std::string>>(); | |
| #if defined(WEBRTC_WIN) | |
| // Append separator character if needed. | |
| if (path.back() != '\\') | |
| path += '\\'; | |
| // Init. | |
| WIN32_FIND_DATA data; | |
| HANDLE handle = ::FindFirstFile(rtc::ToUtf16(path + '*').c_str(), &data); | |
| if (handle == INVALID_HANDLE_VALUE) | |
| return absl::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 + name); | |
| } while (::FindNextFile(handle, &data) == TRUE); | |
| // Release resources. | |
| if (handle != INVALID_HANDLE_VALUE) | |
| ::FindClose(handle); | |
| #else | |
| // Append separator character if needed. | |
| if (path.back() != '/') | |
| path += '/'; | |
| // Init. | |
| DIR* dir = ::opendir(path.c_str()); | |
| if (dir == nullptr) | |
| return absl::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 + name); | |
| } | |
| // Release resources. | |
| closedir(dir); | |
| #endif | |
| return absl::optional<std::vector<std::string>>(std::move(found_entries)); | |
| } | |
| bool CreateDir(const std::string& directory_name) { | |
| struct stat path_info = {0}; | |
| // Check if the path exists already: | |
| if (stat(directory_name.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.c_str()); | |
| return false; | |
| } | |
| } else { | |
| #ifdef WIN32 | |
| return _mkdir(directory_name.c_str()) == 0; | |
| #else | |
| return mkdir(directory_name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0; | |
| #endif | |
| } | |
| return true; | |
| } | |
| bool RemoveDir(const std::string& directory_name) { | |
| #ifdef WIN32 | |
| return RemoveDirectoryA(directory_name.c_str()) != FALSE; | |
| #else | |
| return rmdir(directory_name.c_str()) == 0; | |
| #endif | |
| } | |
| bool RemoveFile(const std::string& file_name) { | |
| #ifdef WIN32 | |
| return DeleteFileA(file_name.c_str()) != FALSE; | |
| #else | |
| return unlink(file_name.c_str()) == 0; | |
| #endif | |
| } | |
| std::string ResourcePath(const std::string& name, | |
| const std::string& extension) { | |
| return webrtc::test::internal::ResourcePath(name, extension); | |
| } | |
| std::string JoinFilename(const std::string& dir, const std::string& name) { | |
| RTC_CHECK(!dir.empty()) << "Special cases not implemented."; | |
| return dir + kPathDelimiter + name; | |
| } | |
| size_t GetFileSize(const std::string& filename) { | |
| FILE* f = fopen(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 |