|
12 | 12 | #ifdef __APPLE__
|
13 | 13 | #include <mach-o/dyld.h>
|
14 | 14 | #endif
|
| 15 | +#ifdef __FreeBSD__ |
| 16 | +#include <sys/param.h> |
| 17 | +#include <sys/sysctl.h> // for GetExecutablePathFreeBSD() |
| 18 | +#endif |
| 19 | +#ifdef __TUW_HAIKU__ |
| 20 | +#include <kernel/image.h> // for GetExecutablePathHaiku() |
| 21 | +#endif |
15 | 22 | #include <sys/stat.h>
|
16 | 23 | #include <unistd.h>
|
17 | 24 | #include <pwd.h>
|
@@ -99,25 +106,79 @@ namespace env_utils {
|
99 | 106 | }
|
100 | 107 | }
|
101 | 108 |
|
| 109 | +#ifdef __TUW_UNIX__ |
| 110 | +#ifdef __FreeBSD__ |
| 111 | + // FreeBSD requires sysctl to get the executable path. |
| 112 | + void GetExecutablePathFreeBSD(char *path) { |
| 113 | + size_t path_size = PATH_MAX; |
| 114 | + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; |
| 115 | + int error = sysctl(mib, 4, path, &path_size, NULL, 0); |
| 116 | + if (error < 0 || path_size == 0) |
| 117 | + path_size = 0; |
| 118 | + path[path_size] = 0; |
| 119 | + } |
| 120 | + |
102 | 121 | std::string GetExecutablePath() {
|
103 | 122 | char path[PATH_MAX + 1];
|
104 | 123 | path[PATH_MAX] = 0;
|
105 |
| - #ifdef __linux__ |
106 |
| - const size_t LINKSIZE = 100; |
107 |
| - char link[LINKSIZE]; |
108 |
| - snprintf(link, LINKSIZE, "/proc/%d/exe", getpid() ); |
109 |
| - int path_size = readlink(link, path, PATH_MAX); |
110 |
| - if (path_size == -1) |
111 |
| - path_size = 0; |
| 124 | + GetExecutablePathFreeBSD(path); |
| 125 | + if (path[0] == 0) |
| 126 | + return "/"; |
| 127 | + return path; |
| 128 | + } |
| 129 | +#elif defined(__TUW_HAIKU__) |
| 130 | + // Haiku OS requires its own API to get the executable path. |
| 131 | + std::string GetExecutablePath() { |
| 132 | + int32_t cookie = 0; |
| 133 | + image_info info; |
| 134 | + while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { |
| 135 | + if (info.type == B_APP_IMAGE) |
| 136 | + return info.name; |
| 137 | + } |
| 138 | + return "/"; |
| 139 | + } |
| 140 | +#else |
| 141 | + // Linux distributons support readlink to get the executable path. |
| 142 | + int TryReadlink(const char *link, char *path, int path_size) { |
| 143 | + int new_path_size; |
| 144 | + if (path_size != 0) |
| 145 | + return path_size; |
| 146 | + new_path_size = readlink(link, path, PATH_MAX); |
| 147 | + if (new_path_size == -1) |
| 148 | + new_path_size = 0; |
| 149 | + return new_path_size; |
| 150 | + } |
| 151 | + |
| 152 | + void GetExecutablePathUnix(char *path) { |
| 153 | + int path_size = 0; |
| 154 | + path_size = TryReadlink("/proc/self/exe", path, path_size); // Linux |
| 155 | + path_size = TryReadlink("/proc/curproc/exe", path, path_size); // NetBSD |
| 156 | + path_size = TryReadlink("/proc/curproc/file", path, path_size); // OpenBSD |
112 | 157 | path[path_size] = 0;
|
113 |
| - #else |
| 158 | + } |
| 159 | + |
| 160 | + std::string GetExecutablePath() { |
| 161 | + char path[PATH_MAX + 1]; |
| 162 | + path[PATH_MAX] = 0; |
| 163 | + GetExecutablePathUnix(path); |
| 164 | + if (path[0] == 0) |
| 165 | + return "/"; |
| 166 | + return path; |
| 167 | + } |
| 168 | +#endif |
| 169 | +#endif // __TUW_UNIX__ |
| 170 | + |
| 171 | +#ifdef __APPLE__ |
| 172 | + std::string GetExecutablePath() { |
| 173 | + char path[PATH_MAX + 1]; |
| 174 | + path[PATH_MAX] = 0; |
114 | 175 | uint32_t bufsize = PATH_MAX;
|
115 | 176 | _NSGetExecutablePath(path, &bufsize);
|
116 |
| - #endif |
117 | 177 | if (path[0] == 0)
|
118 | 178 | return "/";
|
119 | 179 | return path;
|
120 | 180 | }
|
| 181 | +#endif |
121 | 182 |
|
122 | 183 | bool FileExists(const std::string& path) {
|
123 | 184 | struct stat buffer;
|
|
0 commit comments