1 // Copyright 2015 PDFium Authors. All rights reserved.
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 #ifdef _WIN32
8 #include <Windows.h>
9 #elif defined(__APPLE__)
10 #include <mach-o/dyld.h>
11 #else  // Linux
12 #include <linux/limits.h>
13 #include <unistd.h>
14 #endif  // _WIN32
15 
16 #include "core/include/fxcrt/fx_system.h"
17 
18 // static
EndsWithSeparator(const std::string & path)19 bool PathService::EndsWithSeparator(const std::string& path) {
20   return path.size() > 1 && path[path.size() - 1] == PATH_SEPARATOR;
21 }
22 
23 // static
GetExecutableDir(std::string * path)24 bool PathService::GetExecutableDir(std::string* path) {
25 // Get the current executable file path.
26 #ifdef _WIN32
27   char path_buffer[MAX_PATH];
28   path_buffer[0] = 0;
29 
30   if (GetModuleFileNameA(NULL, path_buffer, MAX_PATH) == 0)
31     return false;
32   *path = std::string(path_buffer);
33 #elif defined(__APPLE__)
34   FXSYS_assert(path);
35   unsigned int path_length = 0;
36   _NSGetExecutablePath(NULL, &path_length);
37   if (path_length == 0)
38     return false;
39 
40   path->reserve(path_length);
41   path->resize(path_length - 1);
42   if (_NSGetExecutablePath(&((*path)[0]), &path_length))
43     return false;
44 #else   // Linux
45   static const char kProcSelfExe[] = "/proc/self/exe";
46   char buf[PATH_MAX];
47   ssize_t count = ::readlink(kProcSelfExe, buf, PATH_MAX);
48   if (count <= 0)
49     return false;
50 
51   *path = std::string(buf, count);
52 #endif  // _WIN32
53 
54   // Get the directory path.
55   std::size_t pos = path->size() - 1;
56   if (EndsWithSeparator(*path))
57     pos--;
58   std::size_t found = path->find_last_of(PATH_SEPARATOR, pos);
59   if (found == std::string::npos)
60     return false;
61   path->resize(found);
62   return true;
63 }
64 
65 // static
GetSourceDir(std::string * path)66 bool PathService::GetSourceDir(std::string* path) {
67   if (!GetExecutableDir(path))
68     return false;
69 
70   if (!EndsWithSeparator(*path))
71     path->push_back(PATH_SEPARATOR);
72   path->append("..");
73   path->push_back(PATH_SEPARATOR);
74   path->append("..");
75   return true;
76 }
77 
78 // static
GetTestDataDir(std::string * path)79 bool PathService::GetTestDataDir(std::string* path) {
80   if (!GetSourceDir(path))
81     return false;
82 
83   if (!EndsWithSeparator(*path))
84     path->push_back(PATH_SEPARATOR);
85   path->append("testing");
86   path->push_back(PATH_SEPARATOR);
87   path->append("resources");
88   return true;
89 }
90 
91 // static
GetTestFilePath(const std::string & file_name,std::string * path)92 bool PathService::GetTestFilePath(const std::string& file_name,
93                                   std::string* path) {
94   if (!GetTestDataDir(path))
95     return false;
96 
97   if (!EndsWithSeparator(*path))
98     path->push_back(PATH_SEPARATOR);
99   path->append(file_name);
100   return true;
101 }
102