mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05:00
LibCore: Add Core::System::current_executable_path()
This is based on Jakt::File::current_executable_path() and all the other sources I looked at to figure out the per-platform way to do this. My goodness, every platform has its own bespoke way.
This commit is contained in:
parent
88ccaae11e
commit
bb831a27dd
2 changed files with 45 additions and 0 deletions
|
@ -44,11 +44,16 @@ static int memfd_create(char const* name, unsigned int flags)
|
|||
|
||||
#if defined(AK_OS_MACOS)
|
||||
# include <crt_externs.h>
|
||||
# include <mach-o/dyld.h>
|
||||
# include <sys/mman.h>
|
||||
#else
|
||||
extern char** environ;
|
||||
#endif
|
||||
|
||||
#if defined(AK_OS_BSD_GENERIC)
|
||||
# include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#define HANDLE_SYSCALL_RETURN_VALUE(syscall_name, rc, success_value) \
|
||||
if ((rc) < 0) { \
|
||||
return Error::from_syscall(syscall_name##sv, rc); \
|
||||
|
@ -1726,4 +1731,42 @@ char** environment()
|
|||
#endif
|
||||
}
|
||||
|
||||
ErrorOr<String> current_executable_path()
|
||||
{
|
||||
char path[4096] = {};
|
||||
#if defined(AK_OS_LINUX) || defined(AK_OS_ANDROID) || defined(AK_OS_SERENITY)
|
||||
auto ret = ::readlink("/proc/self/exe", path, sizeof(path) - 1);
|
||||
// Ignore error if it wasn't a symlink
|
||||
if (ret == -1 && errno != EINVAL)
|
||||
return Error::from_syscall("readlink"sv, -errno);
|
||||
#elif defined(AK_OS_DRAGONFLY)
|
||||
return String::from_deprecated_string(TRY(readlink("/proc/curproc/file"sv)));
|
||||
#elif defined(AK_OS_SOLARIS)
|
||||
return String::from_deprecated_string(TRY(readlink("/proc/self/path/a.out"sv)));
|
||||
#elif defined(AK_OS_FREEBSD)
|
||||
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
|
||||
size_t len = sizeof(path);
|
||||
if (sysctl(mib, 4, path, &len, nullptr, 0) < 0)
|
||||
return Errno::from_syscall("sysctl"sv, -errno);
|
||||
#elif defined(AK_OS_NETBSD)
|
||||
int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
|
||||
size_t len = sizeof(path);
|
||||
if (sysctl(mib, 4, path, &len, nullptr, 0) < 0)
|
||||
return Errno::from_syscall("sysctl"sv, -errno);
|
||||
#elif defined(AK_OS_MACOS)
|
||||
u32 size = sizeof(path);
|
||||
auto ret = _NSGetExecutablePath(path, &size);
|
||||
if (ret != 0)
|
||||
return Error::from_errno(ENAMETOOLONG);
|
||||
#elif defined(AK_OS_EMSCRIPTEN)
|
||||
return Error::from_string_view("current_executable_path() unknown on this platform"sv);
|
||||
#else
|
||||
# warning "Not sure how to get current_executable_path on this platform!"
|
||||
// GetModuleFileName on Windows, unsure about OpenBSD.
|
||||
return Error::from_string_view("current_executable_path unknown"sv);
|
||||
#endif
|
||||
path[sizeof(path) - 1] = '\0';
|
||||
return String::from_utf8({ path, strlen(path) });
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -273,4 +273,6 @@ ErrorOr<String> resolve_executable_from_environment(StringView filename, int fla
|
|||
|
||||
char** environment();
|
||||
|
||||
ErrorOr<String> current_executable_path();
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue