1 // Copyright 2018 The Chromium 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 "util/exe_path.h"
6
7 #include "base/files/file_util.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "util/build_config.h"
11
12 #if defined(OS_MACOSX)
13 #include <mach-o/dyld.h>
14 #elif defined(OS_WIN)
15 #include <windows.h>
16
17 #include "base/win/win_util.h"
18 #elif defined(OS_FREEBSD) || defined(OS_NETBSD)
19 #include <limits.h>
20 #include <sys/sysctl.h>
21 #include <sys/types.h>
22 #elif defined(OS_HAIKU)
23 #include <OS.h>
24 #include <image.h>
25 #elif defined(OS_SOLARIS)
26 #include <stdlib.h>
27 #endif
28
29 #if defined(OS_MACOSX)
30
GetExePath()31 base::FilePath GetExePath() {
32 // Executable path can have relative references ("..") depending on
33 // how the app was launched.
34 uint32_t executable_length = 0;
35 _NSGetExecutablePath(NULL, &executable_length);
36 DCHECK_GT(executable_length, 1u);
37 std::string executable_path;
38 int rv = _NSGetExecutablePath(
39 base::WriteInto(&executable_path, executable_length), &executable_length);
40 DCHECK_EQ(rv, 0);
41
42 // _NSGetExecutablePath may return paths containing ./ or ../ which makes
43 // FilePath::DirName() work incorrectly, convert it to absolute path so that
44 // paths such as DIR_SOURCE_ROOT can work, since we expect absolute paths to
45 // be returned here.
46 return base::MakeAbsoluteFilePath(base::FilePath(executable_path));
47 }
48
49 #elif defined(OS_WIN)
50
GetExePath()51 base::FilePath GetExePath() {
52 char16_t system_buffer[MAX_PATH];
53 system_buffer[0] = 0;
54 if (GetModuleFileName(NULL, base::ToWCharT(system_buffer), MAX_PATH) == 0) {
55 return base::FilePath();
56 }
57 return base::FilePath(system_buffer);
58 }
59
60 #elif defined(OS_FREEBSD)
61
GetExePath()62 base::FilePath GetExePath() {
63 int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
64 char buf[PATH_MAX];
65 size_t buf_size = PATH_MAX;
66 if (sysctl(mib, 4, buf, &buf_size, nullptr, 0) == -1) {
67 return base::FilePath();
68 }
69 return base::FilePath(buf);
70 }
71
72 #elif defined(OS_NETBSD)
73
GetExePath()74 base::FilePath GetExePath() {
75 int mib[] = {CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_PATHNAME};
76 char buf[PATH_MAX];
77 size_t buf_size = PATH_MAX;
78 if (sysctl(mib, 4, buf, &buf_size, nullptr, 0) == -1) {
79 return base::FilePath();
80 }
81 return base::FilePath(buf);
82 }
83
84 #elif defined(OS_HAIKU)
85
GetExePath()86 base::FilePath GetExePath() {
87 image_info i_info;
88 int32 image_cookie = 0;
89 while (get_next_image_info(B_CURRENT_TEAM, &image_cookie, &i_info) == B_OK) {
90 if (i_info.type == B_APP_IMAGE) {
91 break;
92 }
93 }
94 return base::FilePath(std::string(i_info.name));
95 }
96
97 #elif defined(OS_SOLARIS)
98
GetExePath()99 base::FilePath GetExePath() {
100 const char *raw = getexecname();
101 if (raw == NULL) {
102 return base::FilePath();
103 }
104 return base::FilePath(raw);
105 }
106
107 #elif defined(OS_ZOS)
108
GetExePath()109 base::FilePath GetExePath() {
110 char path[PATH_MAX];
111 if (__getexepath(path, sizeof(path), getpid()) != 0) {
112 return base::FilePath();
113 }
114 return base::FilePath(path);
115 }
116
117 #else
118
GetExePath()119 base::FilePath GetExePath() {
120 base::FilePath result;
121 const char kProcSelfExe[] = "/proc/self/exe";
122 if (!ReadSymbolicLink(base::FilePath(kProcSelfExe), &result)) {
123 NOTREACHED() << "Unable to resolve " << kProcSelfExe << ".";
124 return base::FilePath();
125 }
126 return result;
127 }
128
129 #endif
130