| /* |
| * Copyright (c) 2025 The Khronos Group Inc. |
| * Copyright (c) 2025 Valve Corporation |
| * Copyright (c) 2025 LunarG, Inc. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a copy |
| * of this software and/or associated documentation files (the "Materials"), to |
| * deal in the Materials without restriction, including without limitation the |
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| * sell copies of the Materials, and to permit persons to whom the Materials are |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice(s) and this permission notice shall be included in |
| * all copies or substantial portions of the Materials. |
| * |
| * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| * |
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE |
| * USE OR OTHER DEALINGS IN THE MATERIALS. |
| * |
| */ |
| |
| #include "get_executable_path.h" |
| |
| #if defined(__linux__) || defined(__GNU__) |
| |
| #include <unistd.h> |
| |
| // find application path + name. Path cannot be longer than 1024, returns NULL if it is greater than that. |
| std::string test_platform_executable_path() { |
| std::string buffer; |
| buffer.resize(1024); |
| ssize_t count = readlink("/proc/self/exe", &buffer[0], buffer.size()); |
| if (count == -1) return NULL; |
| if (count == 0) return NULL; |
| buffer[count] = '\0'; |
| buffer.resize(count); |
| return buffer; |
| } |
| #elif defined(__APPLE__) |
| |
| #include <libproc.h> |
| #include <unistd.h> |
| |
| std::string test_platform_executable_path() { |
| std::string buffer; |
| buffer.resize(1024); |
| pid_t pid = getpid(); |
| int ret = proc_pidpath(pid, &buffer[0], static_cast<uint32_t>(buffer.size())); |
| if (ret <= 0) return NULL; |
| buffer[ret] = '\0'; |
| buffer.resize(ret); |
| return buffer; |
| } |
| #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) |
| #include <sys/sysctl.h> |
| std::string test_platform_executable_path() { |
| int mib[] = { |
| CTL_KERN, |
| #if defined(__NetBSD__) |
| KERN_PROC_ARGS, |
| -1, |
| KERN_PROC_PATHNAME, |
| #else |
| KERN_PROC, |
| KERN_PROC_PATHNAME, |
| -1, |
| #endif |
| }; |
| std::string buffer; |
| buffer.resize(1024); |
| size_t size = buffer.size(); |
| if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &buffer[0], &size, NULL, 0) < 0) { |
| return NULL; |
| } |
| buffer.resize(size); |
| |
| return buffer; |
| } |
| #elif defined(__Fuchsia__) || defined(__OpenBSD__) |
| std::string test_platform_executable_path() { return {}; } |
| #elif defined(__QNX__) |
| |
| #ifndef SYSCONFDIR |
| #define SYSCONFDIR "/etc" |
| #endif |
| |
| #include <fcntl.h> |
| #include <sys/stat.h> |
| |
| std::string test_platform_executable_path() { |
| std::string buffer; |
| buffer.resize(1024); |
| int fd = open("/proc/self/exefile", O_RDONLY); |
| ssize_t rdsize; |
| |
| if (fd == -1) { |
| return NULL; |
| } |
| |
| rdsize = read(fd, &buffer[0], buffer.size()); |
| if (rdsize < 0) { |
| return NULL; |
| } |
| buffer[rdsize] = 0x00; |
| close(fd); |
| buffer.resize(rdsize); |
| |
| return buffer; |
| } |
| #endif // defined (__QNX__) |
| |
| #if defined(_WIN32) |
| |
| #include <filesystem> |
| |
| #include <Windows.h> |
| |
| #include "wide_char_handling.h" |
| |
| std::string test_platform_executable_path() { |
| std::string buffer; |
| buffer.resize(1024); |
| DWORD ret = GetModuleFileName(NULL, static_cast<LPSTR>(&buffer[0]), (DWORD)buffer.size()); |
| if (ret == 0) return NULL; |
| if (ret > buffer.size()) return NULL; |
| buffer.resize(ret); |
| buffer[ret] = '\0'; |
| return narrow(std::filesystem::path(buffer).native()); |
| } |
| |
| #endif |