From 78f0e823542d23b978d10b1aee89849538c58b73 Mon Sep 17 00:00:00 2001 From: Matthew Waltz Date: Sun, 6 Oct 2024 19:19:36 -0600 Subject: [PATCH] [cdev-config] update whereami --- tools/cedev-config/src/whereami.c | 198 ++++++++++++++++++++++++------ tools/cedev-config/src/whereami.h | 6 +- 2 files changed, 165 insertions(+), 39 deletions(-) diff --git a/tools/cedev-config/src/whereami.c b/tools/cedev-config/src/whereami.c index 8ac4803e4..a8a649d73 100644 --- a/tools/cedev-config/src/whereami.c +++ b/tools/cedev-config/src/whereami.c @@ -12,6 +12,15 @@ extern "C" { #endif +#if defined(__linux__) || defined(__CYGWIN__) +#undef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#elif defined(__APPLE__) +#undef _DARWIN_C_SOURCE +#define _DARWIN_C_SOURCE +#define _DARWIN_BETTER_REALPATH +#endif + #if !defined(WAI_MALLOC) || !defined(WAI_FREE) || !defined(WAI_REALLOC) #include #endif @@ -55,11 +64,17 @@ extern "C" { #pragma warning(push, 3) #endif #include -// The following may not always be available and doesn't seem to be necessary: -// #include +#include #if defined(_MSC_VER) #pragma warning(pop) #endif +#if (_MSC_VER >= 1900) +#include +#else +#define bool int +#define false 0 +#define true 1 +#endif static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length) { @@ -67,8 +82,9 @@ static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, i wchar_t buffer2[MAX_PATH]; wchar_t* path = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { DWORD size; int length_, length__; @@ -124,14 +140,12 @@ static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, i } length = length__; - - break; } if (path != buffer1) WAI_FREE(path); - return length; + return ok ? length : -1; } WAI_NOINLINE WAI_FUNCSPEC @@ -175,6 +189,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) #define __STDC_FORMAT_MACROS #endif #include +#include #if !defined(WAI_PROC_SELF_EXE) #if defined(__sun) @@ -190,8 +205,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) char buffer[PATH_MAX]; char* resolved = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { resolved = realpath(WAI_PROC_SELF_EXE, buffer); if (!resolved) @@ -216,11 +232,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) } } } - - break; } - return length; + return ok ? length : -1; } #if !defined(WAI_PROC_SELF_MAPS_RETRY) @@ -235,11 +249,17 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) #endif #endif +#if !defined(WAI_STRINGIZE) +#define WAI_STRINGIZE(s) +#define WAI_STRINGIZE_(s) #s +#endif + #if defined(__ANDROID__) || defined(ANDROID) #include #include #include #endif +#include WAI_NOINLINE WAI_FUNCSPEC int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) @@ -255,20 +275,20 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) for (;;) { - char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX]; - uint64_t low, high; + char buffer[128 + PATH_MAX]; + uintptr_t low, high; char perms[5]; uint64_t offset; - uint32_t major, minor; - char path[PATH_MAX]; - uint32_t inode; + uint32_t major, minor, inode; + char path[PATH_MAX + 1]; if (!fgets(buffer, sizeof(buffer), maps)) break; - if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8) + if (sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR " %s %" SCNx64 " %x:%x %u %" WAI_STRINGIZE(PATH_MAX) "[^\n]\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8) { - uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS(); + void* _addr = WAI_RETURN_ADDRESS(); + uintptr_t addr = (uintptr_t)_addr; if (low <= addr && addr <= high) { char* resolved; @@ -355,20 +375,17 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) break; } - if (maps) - fclose(maps); - return length; } #elif defined(__APPLE__) -#define _DARWIN_BETTER_REALPATH #include #include #include #include #include +#include WAI_FUNCSPEC int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) @@ -378,8 +395,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) char* path = buffer1; char* resolved = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { uint32_t size = (uint32_t)sizeof(buffer1); if (_NSGetExecutablePath(path, &size) == -1) @@ -412,14 +430,12 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) } } } - - break; } if (path != buffer1) WAI_FREE(path); - return length; + return ok ? length : -1; } WAI_NOINLINE WAI_FUNCSPEC @@ -473,6 +489,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) #include #include #include +#include #if !defined(WAI_PROC_SELF_EXE) #define WAI_PROC_SELF_EXE "/proc/self/exefile" @@ -486,8 +503,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) char* resolved = NULL; FILE* self_exe = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { self_exe = fopen(WAI_PROC_SELF_EXE, "r"); if (!self_exe) @@ -519,13 +537,11 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) } } } - - break; } fclose(self_exe); - return length; + return ok ? length : -1; } WAI_FUNCSPEC @@ -573,7 +589,7 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) } #elif defined(__DragonFly__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__NetBSD__) + defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) #include #include @@ -581,6 +597,116 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) #include #include #include +#include + +#if defined(__OpenBSD__) + +#include + +WAI_FUNCSPEC +int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) +{ + char buffer1[4096]; + char buffer2[PATH_MAX]; + char buffer3[PATH_MAX]; + char** argv = (char**)buffer1; + char* resolved = NULL; + int length = -1; + bool ok; + + for (ok = false; !ok; ok = true) + { + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; + size_t size; + + if (sysctl(mib, 4, NULL, &size, NULL, 0) != 0) + break; + + if (size > sizeof(buffer1)) + { + argv = (char**)WAI_MALLOC(size); + if (!argv) + break; + } + + if (sysctl(mib, 4, argv, &size, NULL, 0) != 0) + break; + + if (strchr(argv[0], '/')) + { + resolved = realpath(argv[0], buffer2); + if (!resolved) + break; + } + else + { + const char* PATH = getenv("PATH"); + if (!PATH) + break; + + size_t argv0_length = strlen(argv[0]); + + const char* begin = PATH; + while (1) + { + const char* separator = strchr(begin, ':'); + const char* end = separator ? separator : begin + strlen(begin); + + if (end - begin > 0) + { + if (*(end -1) == '/') + --end; + + if (((end - begin) + 1 + argv0_length + 1) <= sizeof(buffer2)) + { + memcpy(buffer2, begin, end - begin); + buffer2[end - begin] = '/'; + memcpy(buffer2 + (end - begin) + 1, argv[0], argv0_length + 1); + + resolved = realpath(buffer2, buffer3); + if (resolved) + break; + } + } + + if (!separator) + break; + + begin = ++separator; + } + + if (!resolved) + break; + } + + length = (int)strlen(resolved); + if (length <= capacity) + { + memcpy(out, resolved, length); + + if (dirname_length) + { + int i; + + for (i = length - 1; i >= 0; --i) + { + if (out[i] == '/') + { + *dirname_length = i; + break; + } + } + } + } + } + + if (argv != (char**)buffer1) + WAI_FREE(argv); + + return ok ? length : -1; +} + +#else WAI_FUNCSPEC int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) @@ -590,8 +716,9 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) char* path = buffer1; char* resolved = NULL; int length = -1; + bool ok; - for (;;) + for (ok = false; !ok; ok = true) { #if defined(__NetBSD__) int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME }; @@ -626,16 +753,13 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) } } } - - break; } - if (path != buffer1) - WAI_FREE(path); - - return length; + return ok ? length : -1; } +#endif + WAI_NOINLINE WAI_FUNCSPEC int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length) { diff --git a/tools/cedev-config/src/whereami.h b/tools/cedev-config/src/whereami.h index 670db54c3..8e58c8185 100644 --- a/tools/cedev-config/src/whereami.h +++ b/tools/cedev-config/src/whereami.h @@ -31,7 +31,8 @@ extern "C" { * @param out destination buffer, optional * @param capacity destination buffer capacity * @param dirname_length optional recipient for the length of the dirname part - * of the path. + * of the path. Available only when `capacity` is large enough to retrieve the + * path. * * @return the length of the executable path on success (without a terminal NUL * character), otherwise `-1` @@ -52,7 +53,8 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length); * @param out destination buffer, optional * @param capacity destination buffer capacity * @param dirname_length optional recipient for the length of the dirname part - * of the path. + * of the path. Available only when `capacity` is large enough to retrieve the + * path. * * @return the length of the module path on success (without a terminal NUL * character), otherwise `-1`