| // Copyright 2015 The PDFium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "testing/utils/path_service.h" | |
| #include <stddef.h> | |
| #ifdef _WIN32 | |
| #include <Windows.h> | |
| #elif defined(__APPLE__) | |
| #include <mach-o/dyld.h> | |
| #include <sys/stat.h> | |
| #else // Linux | |
| #include <linux/limits.h> | |
| #include <sys/stat.h> | |
| #include <unistd.h> | |
| #endif // _WIN32 | |
| #include <string> | |
| #include "core/fxcrt/check.h" | |
| #include "core/fxcrt/fx_system.h" | |
| namespace { | |
| #if defined(__APPLE__) || (defined(ANDROID) && __ANDROID_API__ < 21) | |
| using stat_wrapper_t = struct stat; | |
| int CallStat(const char* path, stat_wrapper_t* sb) { | |
| return stat(path, sb); | |
| } | |
| #elif !_WIN32 | |
| using stat_wrapper_t = struct stat64; | |
| int CallStat(const char* path, stat_wrapper_t* sb) { | |
| return stat64(path, sb); | |
| } | |
| #endif | |
| void MaybeAppendPdfiumPathInChromiumCheckout(std::string& path) { | |
| #ifdef BUILD_WITH_CHROMIUM | |
| path.append("third_party"); | |
| path.push_back(PATH_SEPARATOR); | |
| path.append("pdfium"); | |
| path.push_back(PATH_SEPARATOR); | |
| #endif | |
| } | |
| } // namespace | |
| // static | |
| bool PathService::DirectoryExists(const std::string& path) { | |
| #ifdef _WIN32 | |
| DWORD fileattr = GetFileAttributesA(path.c_str()); | |
| if (fileattr != INVALID_FILE_ATTRIBUTES) { | |
| return (fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0; | |
| } | |
| return false; | |
| #else | |
| stat_wrapper_t file_info; | |
| if (CallStat(path.c_str(), &file_info) != 0) { | |
| return false; | |
| } | |
| return S_ISDIR(file_info.st_mode); | |
| #endif | |
| } | |
| // static | |
| bool PathService::EndsWithSeparator(const std::string& path) { | |
| return path.size() > 1 && path[path.size() - 1] == PATH_SEPARATOR; | |
| } | |
| // static | |
| std::string PathService::GetExecutableDir() { | |
| std::string path; | |
| // Get the current executable file path. | |
| #ifdef _WIN32 | |
| char path_buffer[MAX_PATH]; | |
| path_buffer[0] = 0; | |
| if (GetModuleFileNameA(nullptr, path_buffer, MAX_PATH) == 0) { | |
| return std::string(); | |
| } | |
| path = std::string(path_buffer); | |
| #elif defined(__APPLE__) | |
| unsigned int path_length = 0; | |
| _NSGetExecutablePath(nullptr, &path_length); | |
| if (path_length == 0) { | |
| return std::string(); | |
| } | |
| path.reserve(path_length); | |
| path.resize(path_length - 1); | |
| if (_NSGetExecutablePath(&path[0], &path_length)) { | |
| return std::string(); | |
| } | |
| #else // Linux | |
| static const char kProcSelfExe[] = "/proc/self/exe"; | |
| char buf[PATH_MAX]; | |
| ssize_t count = ::readlink(kProcSelfExe, buf, PATH_MAX); | |
| if (count <= 0) { | |
| return std::string(); | |
| } | |
| path = std::string(buf, count); | |
| #endif // _WIN32 | |
| // Get the directory path. | |
| size_t pos = path.size() - 1; | |
| if (EndsWithSeparator(path)) { | |
| pos--; | |
| } | |
| size_t found = path.find_last_of(PATH_SEPARATOR, pos); | |
| if (found == std::string::npos) { | |
| return std::string(); | |
| } | |
| path.resize(found); | |
| return path; | |
| } | |
| // static | |
| std::string PathService::GetSourceDir() { | |
| std::string path = GetExecutableDir(); | |
| if (path.empty()) { | |
| return std::string(); | |
| } | |
| if (!EndsWithSeparator(path)) { | |
| path.push_back(PATH_SEPARATOR); | |
| } | |
| path.append(".."); | |
| path.push_back(PATH_SEPARATOR); | |
| #if defined(ANDROID) | |
| path.append("chromium_tests_root"); | |
| #else // Non-Android | |
| path.append(".."); | |
| #endif // defined(ANDROID) | |
| return path; | |
| } | |
| // static | |
| std::string PathService::GetTestDataDir() { | |
| std::string path = GetSourceDir(); | |
| if (path.empty()) { | |
| return std::string(); | |
| } | |
| if (!EndsWithSeparator(path)) { | |
| path.push_back(PATH_SEPARATOR); | |
| } | |
| MaybeAppendPdfiumPathInChromiumCheckout(path); | |
| path.append("testing"); | |
| path.push_back(PATH_SEPARATOR); | |
| path.append("resources"); | |
| if (!PathService::DirectoryExists(path)) { | |
| return std::string(); | |
| } | |
| return path; | |
| } | |
| // static | |
| std::string PathService::GetTestFilePath(const std::string& file_name) { | |
| std::string path = GetTestDataDir(); | |
| if (path.empty()) { | |
| return std::string(); | |
| } | |
| if (!EndsWithSeparator(path)) { | |
| path.push_back(PATH_SEPARATOR); | |
| } | |
| path.append(file_name); | |
| return path; | |
| } | |
| // static | |
| std::string PathService::GetThirdPartyFilePath(const std::string& file_name) { | |
| std::string path = GetSourceDir(); | |
| if (path.empty()) { | |
| return std::string(); | |
| } | |
| if (!EndsWithSeparator(path)) { | |
| path.push_back(PATH_SEPARATOR); | |
| } | |
| MaybeAppendPdfiumPathInChromiumCheckout(path); | |
| path.append("third_party"); | |
| if (!PathService::DirectoryExists(path)) { | |
| return std::string(); | |
| } | |
| path.push_back(PATH_SEPARATOR); | |
| path.append(file_name); | |
| return path; | |
| } |