• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "testing/utils/path_service.h"
6 
7 #include <stddef.h>
8 
9 #ifdef _WIN32
10 #include <Windows.h>
11 #elif defined(__APPLE__)
12 #include <mach-o/dyld.h>
13 #include <sys/stat.h>
14 #else  // Linux
15 #include <linux/limits.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #endif  // _WIN32
19 
20 #include <string>
21 
22 #include "core/fxcrt/check.h"
23 #include "core/fxcrt/fx_system.h"
24 
25 namespace {
26 
27 #if defined(__APPLE__) || (defined(ANDROID) && __ANDROID_API__ < 21)
28 using stat_wrapper_t = struct stat;
29 
CallStat(const char * path,stat_wrapper_t * sb)30 int CallStat(const char* path, stat_wrapper_t* sb) {
31   return stat(path, sb);
32 }
33 #elif !_WIN32
34 using stat_wrapper_t = struct stat64;
35 
36 int CallStat(const char* path, stat_wrapper_t* sb) {
37   return stat64(path, sb);
38 }
39 #endif
40 
41 }  // namespace
42 
43 // static
DirectoryExists(const std::string & path)44 bool PathService::DirectoryExists(const std::string& path) {
45 #ifdef _WIN32
46   DWORD fileattr = GetFileAttributesA(path.c_str());
47   if (fileattr != INVALID_FILE_ATTRIBUTES)
48     return (fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0;
49   return false;
50 #else
51   stat_wrapper_t file_info;
52   if (CallStat(path.c_str(), &file_info) != 0)
53     return false;
54   return S_ISDIR(file_info.st_mode);
55 #endif
56 }
57 
58 // static
EndsWithSeparator(const std::string & path)59 bool PathService::EndsWithSeparator(const std::string& path) {
60   return path.size() > 1 && path[path.size() - 1] == PATH_SEPARATOR;
61 }
62 
63 // static
GetExecutableDir(std::string * path)64 bool PathService::GetExecutableDir(std::string* path) {
65 // Get the current executable file path.
66 #ifdef _WIN32
67   char path_buffer[MAX_PATH];
68   path_buffer[0] = 0;
69 
70   if (GetModuleFileNameA(NULL, path_buffer, MAX_PATH) == 0)
71     return false;
72   *path = std::string(path_buffer);
73 #elif defined(__APPLE__)
74   DCHECK(path);
75   unsigned int path_length = 0;
76   _NSGetExecutablePath(NULL, &path_length);
77   if (path_length == 0)
78     return false;
79 
80   path->reserve(path_length);
81   path->resize(path_length - 1);
82   if (_NSGetExecutablePath(&((*path)[0]), &path_length))
83     return false;
84 #else   // Linux
85   static const char kProcSelfExe[] = "/proc/self/exe";
86   char buf[PATH_MAX];
87   ssize_t count = ::readlink(kProcSelfExe, buf, PATH_MAX);
88   if (count <= 0)
89     return false;
90 
91   *path = std::string(buf, count);
92 #endif  // _WIN32
93 
94   // Get the directory path.
95   size_t pos = path->size() - 1;
96   if (EndsWithSeparator(*path))
97     pos--;
98   size_t found = path->find_last_of(PATH_SEPARATOR, pos);
99   if (found == std::string::npos)
100     return false;
101   path->resize(found);
102   return true;
103 }
104 
105 // static
GetSourceDir(std::string * path)106 bool PathService::GetSourceDir(std::string* path) {
107   if (!GetExecutableDir(path))
108     return false;
109 
110   if (!EndsWithSeparator(*path))
111     path->push_back(PATH_SEPARATOR);
112   path->append("..");
113   path->push_back(PATH_SEPARATOR);
114 #if defined(ANDROID)
115   path->append("chromium_tests_root");
116 #else   // Non-Android
117   path->append("..");
118 #endif  // defined(ANDROID)
119   return true;
120 }
121 
122 // static
GetTestDataDir(std::string * path)123 bool PathService::GetTestDataDir(std::string* path) {
124   if (!GetSourceDir(path))
125     return false;
126 
127   if (!EndsWithSeparator(*path))
128     path->push_back(PATH_SEPARATOR);
129 
130   std::string potential_path = *path;
131   potential_path.append("testing");
132   potential_path.push_back(PATH_SEPARATOR);
133   potential_path.append("resources");
134   if (PathService::DirectoryExists(potential_path)) {
135     *path = potential_path;
136     return true;
137   }
138 
139   potential_path = *path;
140   potential_path.append("third_party");
141   potential_path.push_back(PATH_SEPARATOR);
142   potential_path.append("pdfium");
143   potential_path.push_back(PATH_SEPARATOR);
144   potential_path.append("testing");
145   potential_path.push_back(PATH_SEPARATOR);
146   potential_path.append("resources");
147   if (PathService::DirectoryExists(potential_path)) {
148     *path = potential_path;
149     return true;
150   }
151 
152   return false;
153 }
154 
155 // static
GetTestFilePath(const std::string & file_name)156 std::string PathService::GetTestFilePath(const std::string& file_name) {
157   std::string path;
158   if (!GetTestDataDir(&path)) {
159     return std::string();
160   }
161 
162   if (!EndsWithSeparator(path)) {
163     path.push_back(PATH_SEPARATOR);
164   }
165   path.append(file_name);
166   return path;
167 }
168 
169 // static
GetThirdPartyFilePath(const std::string & file_name,std::string * path)170 bool PathService::GetThirdPartyFilePath(const std::string& file_name,
171                                         std::string* path) {
172   if (!GetSourceDir(path))
173     return false;
174 
175   if (!EndsWithSeparator(*path))
176     path->push_back(PATH_SEPARATOR);
177 
178   std::string potential_path = *path;
179   potential_path.append("third_party");
180 
181   // Use third_party/bigint as a way to distinguish PDFium's vs. other's.
182   std::string bigint = potential_path + PATH_SEPARATOR + "bigint";
183   if (PathService::DirectoryExists(bigint)) {
184     *path = potential_path;
185     path->append(PATH_SEPARATOR + file_name);
186     return true;
187   }
188 
189   potential_path = *path;
190   potential_path.append("third_party");
191   potential_path.push_back(PATH_SEPARATOR);
192   potential_path.append("pdfium");
193   potential_path.push_back(PATH_SEPARATOR);
194   potential_path.append("third_party");
195   bigint = potential_path + PATH_SEPARATOR + "bigint";
196   if (PathService::DirectoryExists(potential_path)) {
197     *path = potential_path;
198     path->append(PATH_SEPARATOR + file_name);
199     return true;
200   }
201 
202   return false;
203 }
204