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