llvm.org GIT mirror llvm / 50188c1
Port GetMainExecutable over to PathV2. I will remove the V1 version as soon as I change clang in the next commit. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184914 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 6 years ago
6 changed file(s) with 126 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
695695 /// platform specific error_code.
696696 error_code unmap_file_pages(void *base, size_t size);
697697
698
698 /// Return the path to the main executable, given the value of argv[0] from
699 /// program startup and the address of main itself. In extremis, this function
700 /// may fail and return an empty path.
701 std::string getMainExecutable(const char *argv0, void *MainExecAddr);
699702
700703 /// @}
701704 /// @name Iterators
108108 namespace llvm {
109109 namespace sys {
110110 namespace fs {
111 #if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
112 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \
113 defined(__linux__) || defined(__CYGWIN__)
114 static int
115 test_dir(char buf[PATH_MAX], char ret[PATH_MAX],
116 const char *dir, const char *bin)
117 {
118 struct stat sb;
119
120 snprintf(buf, PATH_MAX, "%s/%s", dir, bin);
121 if (realpath(buf, ret) == NULL)
122 return (1);
123 if (stat(buf, &sb) != 0)
124 return (1);
125
126 return (0);
127 }
128
129 static char *
130 getprogpath(char ret[PATH_MAX], const char *bin)
131 {
132 char *pv, *s, *t, buf[PATH_MAX];
133
134 /* First approach: absolute path. */
135 if (bin[0] == '/') {
136 if (test_dir(buf, ret, "/", bin) == 0)
137 return (ret);
138 return (NULL);
139 }
140
141 /* Second approach: relative path. */
142 if (strchr(bin, '/') != NULL) {
143 if (getcwd(buf, PATH_MAX) == NULL)
144 return (NULL);
145 if (test_dir(buf, ret, buf, bin) == 0)
146 return (ret);
147 return (NULL);
148 }
149
150 /* Third approach: $PATH */
151 if ((pv = getenv("PATH")) == NULL)
152 return (NULL);
153 s = pv = strdup(pv);
154 if (pv == NULL)
155 return (NULL);
156 while ((t = strsep(&s, ":")) != NULL) {
157 if (test_dir(buf, ret, t, bin) == 0) {
158 free(pv);
159 return (ret);
160 }
161 }
162 free(pv);
163 return (NULL);
164 }
165 #endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__
166
167 /// GetMainExecutable - Return the path to the main executable, given the
168 /// value of argv[0] from program startup.
169 std::string getMainExecutable(const char *argv0, void *MainAddr) {
170 #if defined(__APPLE__)
171 // On OS X the executable path is saved to the stack by dyld. Reading it
172 // from there is much faster than calling dladdr, especially for large
173 // binaries with symbols.
174 char exe_path[MAXPATHLEN];
175 uint32_t size = sizeof(exe_path);
176 if (_NSGetExecutablePath(exe_path, &size) == 0) {
177 char link_path[MAXPATHLEN];
178 if (realpath(exe_path, link_path))
179 return Path(link_path);
180 }
181 #elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
182 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__)
183 char exe_path[PATH_MAX];
184
185 if (getprogpath(exe_path, argv0) != NULL)
186 return Path(exe_path);
187 #elif defined(__linux__) || defined(__CYGWIN__)
188 char exe_path[MAXPATHLEN];
189 StringRef aPath("/proc/self/exe");
190 if (sys::fs::exists(aPath)) {
191 // /proc is not always mounted under Linux (chroot for example).
192 ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path));
193 if (len >= 0)
194 return StringRef(exe_path, len);
195 } else {
196 // Fall back to the classical detection.
197 if (getprogpath(exe_path, argv0) != NULL)
198 return exe_path;
199 }
200 #elif defined(HAVE_DLFCN_H)
201 // Use dladdr to get executable path if available.
202 Dl_info DLInfo;
203 int err = dladdr(MainAddr, &DLInfo);
204 if (err == 0)
205 return Path();
206
207 // If the filename is a symlink, we need to resolve and return the location of
208 // the actual executable.
209 char link_path[MAXPATHLEN];
210 if (realpath(DLInfo.dli_fname, link_path))
211 return Path(link_path);
212 #else
213 #error GetMainExecutable is not implemented on this host yet.
214 #endif
215 return "";
216 }
111217
112218 TimeValue file_status::getLastModificationTime() const {
113219 TimeValue Ret;
126126 namespace llvm {
127127 namespace sys {
128128 namespace fs {
129
130 std::string getMainExecutable(const char *argv0, void *MainExecAddr) {
131 char pathname[MAX_PATH];
132 DWORD ret = ::GetModuleFileNameA(NULL, pathname, MAX_PATH);
133 return ret != MAX_PATH ? pathname : "";
134 }
135
129136
130137 TimeValue file_status::getLastModificationTime() const {
131138 ULARGE_INTEGER UI;
251251 // Check the directory that the calling program is in. We can do
252252 // this if ProgramPath contains at least one / character, indicating that it
253253 // is a relative path to the executable itself.
254 sys::Path Main = sys::Path::GetMainExecutable(Argv0, MainAddr);
255 StringRef Result = sys::path::parent_path(Main.str());
254 std::string Main = sys::fs::getMainExecutable(Argv0, MainAddr);
255 StringRef Result = sys::path::parent_path(Main);
256256
257257 if (!Result.empty()) {
258258 SmallString<128> Storage = Result;
161161 }
162162
163163 /// \brief Compute the path to the main executable.
164 llvm::sys::Path GetExecutablePath(const char *Argv0) {
164 std::string GetExecutablePath(const char *Argv0) {
165165 // This just needs to be some symbol in the binary; C++ doesn't
166166 // allow taking the address of ::main however.
167167 void *P = (void*) (intptr_t) GetExecutablePath;
168 return llvm::sys::Path::GetMainExecutable(Argv0, P);
168 return llvm::sys::fs::getMainExecutable(Argv0, P);
169169 }
170170
171171 int main(int argc, char **argv) {
179179 // tree.
180180 bool IsInDevelopmentTree;
181181 enum { MakefileStyle, CMakeStyle, CMakeBuildModeStyle } DevelopmentTreeLayout;
182 llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]).str());
182 llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]));
183183 std::string CurrentExecPrefix;
184184 std::string ActiveObjRoot;
185185
77 //===----------------------------------------------------------------------===//
88
99 #include "llvm/Support/CommandLine.h"
10 #include "llvm/Support/FileSystem.h"
1011 #include "llvm/Support/Path.h"
1112 #include "llvm/Support/PathV1.h"
1213 #include "llvm/Support/Program.h"
5556 exit(1);
5657 }
5758
58 Path my_exe = Path::GetMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
59 std::string my_exe =
60 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
5961 const char *argv[] = {
6062 my_exe.c_str(),
6163 "--gtest_filter=ProgramTest.CreateProcessTrailingSlashChild",
7981 StringRef nul("/dev/null");
8082 #endif
8183 const StringRef *redirects[] = { &nul, &nul, 0 };
82 int rc = ExecuteAndWait(my_exe.str(), argv, &envp[0], redirects,
84 int rc = ExecuteAndWait(my_exe, argv, &envp[0], redirects,
8385 /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &error,
8486 &ExecutionFailed);
8587 EXPECT_FALSE(ExecutionFailed) << error;