| // 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 |
| |
| } // 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 |
| bool PathService::GetExecutableDir(std::string* path) { |
| // Get the current executable file path. |
| #ifdef _WIN32 |
| char path_buffer[MAX_PATH]; |
| path_buffer[0] = 0; |
| |
| if (GetModuleFileNameA(NULL, path_buffer, MAX_PATH) == 0) |
| return false; |
| *path = std::string(path_buffer); |
| #elif defined(__APPLE__) |
| DCHECK(path); |
| unsigned int path_length = 0; |
| _NSGetExecutablePath(NULL, &path_length); |
| if (path_length == 0) |
| return false; |
| |
| path->reserve(path_length); |
| path->resize(path_length - 1); |
| if (_NSGetExecutablePath(&((*path)[0]), &path_length)) |
| return false; |
| #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 false; |
| |
| *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 false; |
| path->resize(found); |
| return true; |
| } |
| |
| // static |
| bool PathService::GetSourceDir(std::string* path) { |
| if (!GetExecutableDir(path)) |
| return false; |
| |
| 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 true; |
| } |
| |
| // static |
| bool PathService::GetTestDataDir(std::string* path) { |
| if (!GetSourceDir(path)) |
| return false; |
| |
| if (!EndsWithSeparator(*path)) |
| path->push_back(PATH_SEPARATOR); |
| |
| std::string potential_path = *path; |
| potential_path.append("testing"); |
| potential_path.push_back(PATH_SEPARATOR); |
| potential_path.append("resources"); |
| if (PathService::DirectoryExists(potential_path)) { |
| *path = potential_path; |
| return true; |
| } |
| |
| potential_path = *path; |
| potential_path.append("third_party"); |
| potential_path.push_back(PATH_SEPARATOR); |
| potential_path.append("pdfium"); |
| potential_path.push_back(PATH_SEPARATOR); |
| potential_path.append("testing"); |
| potential_path.push_back(PATH_SEPARATOR); |
| potential_path.append("resources"); |
| if (PathService::DirectoryExists(potential_path)) { |
| *path = potential_path; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // static |
| std::string PathService::GetTestFilePath(const std::string& file_name) { |
| std::string path; |
| if (!GetTestDataDir(&path)) { |
| return std::string(); |
| } |
| |
| if (!EndsWithSeparator(path)) { |
| path.push_back(PATH_SEPARATOR); |
| } |
| path.append(file_name); |
| return path; |
| } |
| |
| // static |
| bool PathService::GetThirdPartyFilePath(const std::string& file_name, |
| std::string* path) { |
| if (!GetSourceDir(path)) |
| return false; |
| |
| if (!EndsWithSeparator(*path)) |
| path->push_back(PATH_SEPARATOR); |
| |
| std::string potential_path = *path; |
| potential_path.append("third_party"); |
| |
| // Use third_party/bigint as a way to distinguish PDFium's vs. other's. |
| std::string bigint = potential_path + PATH_SEPARATOR + "bigint"; |
| if (PathService::DirectoryExists(bigint)) { |
| *path = potential_path; |
| path->append(PATH_SEPARATOR + file_name); |
| return true; |
| } |
| |
| potential_path = *path; |
| potential_path.append("third_party"); |
| potential_path.push_back(PATH_SEPARATOR); |
| potential_path.append("pdfium"); |
| potential_path.push_back(PATH_SEPARATOR); |
| potential_path.append("third_party"); |
| bigint = potential_path + PATH_SEPARATOR + "bigint"; |
| if (PathService::DirectoryExists(potential_path)) { |
| *path = potential_path; |
| path->append(PATH_SEPARATOR + file_name); |
| return true; |
| } |
| |
| return false; |
| } |