|
35 | 35 | #include <windows.h> |
36 | 36 | #include <process.h> // _beginthread |
37 | 37 | #endif |
| 38 | +#if defined(__APPLE__) |
| 39 | +#include <mach-o/dyld.h> |
| 40 | +#endif |
38 | 41 |
|
39 | 42 | #include "cutils.h" |
40 | 43 |
|
@@ -1201,6 +1204,109 @@ int64_t js__gettimeofday_us(void) { |
1201 | 1204 | return ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec; |
1202 | 1205 | } |
1203 | 1206 |
|
| 1207 | +#if defined(_WIN32) |
| 1208 | +int js_exepath(char *buffer, size_t *size_ptr) { |
| 1209 | + int utf8_len, utf16_buffer_len, utf16_len; |
| 1210 | + WCHAR* utf16_buffer; |
| 1211 | + |
| 1212 | + if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) |
| 1213 | + return -1; |
| 1214 | + |
| 1215 | + if (*size_ptr > 32768) { |
| 1216 | + /* Windows paths can never be longer than this. */ |
| 1217 | + utf16_buffer_len = 32768; |
| 1218 | + } else { |
| 1219 | + utf16_buffer_len = (int)*size_ptr; |
| 1220 | + } |
| 1221 | + |
| 1222 | + utf16_buffer = malloc(sizeof(WCHAR) * utf16_buffer_len); |
| 1223 | + if (!utf16_buffer) |
| 1224 | + return -1; |
| 1225 | + |
| 1226 | + /* Get the path as UTF-16. */ |
| 1227 | + utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len); |
| 1228 | + if (utf16_len <= 0) |
| 1229 | + goto error; |
| 1230 | + |
| 1231 | + /* Convert to UTF-8 */ |
| 1232 | + utf8_len = WideCharToMultiByte(CP_UTF8, |
| 1233 | + 0, |
| 1234 | + utf16_buffer, |
| 1235 | + -1, |
| 1236 | + buffer, |
| 1237 | + (int)*size_ptr, |
| 1238 | + NULL, |
| 1239 | + NULL); |
| 1240 | + if (utf8_len == 0) |
| 1241 | + goto error; |
| 1242 | + |
| 1243 | + free(utf16_buffer); |
| 1244 | + |
| 1245 | + /* utf8_len *does* include the terminating null at this point, but the |
| 1246 | + * returned size shouldn't. */ |
| 1247 | + *size_ptr = utf8_len - 1; |
| 1248 | + return 0; |
| 1249 | + |
| 1250 | +error: |
| 1251 | + free(utf16_buffer); |
| 1252 | + return -1; |
| 1253 | +} |
| 1254 | +#elif defined(__APPLE__) |
| 1255 | +int js_exepath(char *buffer, size_t *size) { |
| 1256 | + /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */ |
| 1257 | + char abspath[PATH_MAX * 2 + 1]; |
| 1258 | + char exepath[PATH_MAX + 1]; |
| 1259 | + uint32_t exepath_size; |
| 1260 | + size_t abspath_size; |
| 1261 | + |
| 1262 | + if (buffer == NULL || size == NULL || *size == 0) |
| 1263 | + return -1; |
| 1264 | + |
| 1265 | + exepath_size = sizeof(exepath); |
| 1266 | + if (_NSGetExecutablePath(exepath, &exepath_size)) |
| 1267 | + return -1; |
| 1268 | + |
| 1269 | + if (realpath(exepath, abspath) != abspath) |
| 1270 | + return -1; |
| 1271 | + |
| 1272 | + abspath_size = strlen(abspath); |
| 1273 | + if (abspath_size == 0) |
| 1274 | + return -1; |
| 1275 | + |
| 1276 | + *size -= 1; |
| 1277 | + if (*size > abspath_size) |
| 1278 | + *size = abspath_size; |
| 1279 | + |
| 1280 | + memcpy(buffer, abspath, *size); |
| 1281 | + buffer[*size] = '\0'; |
| 1282 | + |
| 1283 | + return 0; |
| 1284 | +} |
| 1285 | +#elif defined(__linux__) |
| 1286 | +int js_exepath(char *buffer, size_t *size) { |
| 1287 | + ssize_t n; |
| 1288 | + |
| 1289 | + if (buffer == NULL || size == NULL || *size == 0) |
| 1290 | + return -1; |
| 1291 | + |
| 1292 | + n = *size - 1; |
| 1293 | + if (n > 0) |
| 1294 | + n = readlink("/proc/self/exe", buffer, n); |
| 1295 | + |
| 1296 | + if (n == -1) |
| 1297 | + return n; |
| 1298 | + |
| 1299 | + buffer[n] = '\0'; |
| 1300 | + *size = n; |
| 1301 | + |
| 1302 | + return 0; |
| 1303 | +} |
| 1304 | +#else |
| 1305 | +int js_exepath(char* buffer, size_t* size_ptr) { |
| 1306 | + return -1; |
| 1307 | +} |
| 1308 | +#endif |
| 1309 | + |
1204 | 1310 | /*--- Cross-platform threading APIs. ----*/ |
1205 | 1311 |
|
1206 | 1312 | #if JS_HAVE_THREADS |
|
0 commit comments