diff --git a/bee/sys/path_helper.h b/bee/sys/path.h similarity index 88% rename from bee/sys/path_helper.h rename to bee/sys/path.h index 57b69069..017d112a 100644 --- a/bee/sys/path_helper.h +++ b/bee/sys/path.h @@ -3,7 +3,7 @@ #include #include -namespace bee::path_helper { +namespace bee::sys { using path_expected = expected; path_expected exe_path() noexcept; path_expected dll_path() noexcept; diff --git a/bee/sys/path_bsd.cpp b/bee/sys/path_bsd.cpp new file mode 100644 index 00000000..7c07afc7 --- /dev/null +++ b/bee/sys/path_bsd.cpp @@ -0,0 +1,50 @@ +#include +#include +#include + +#if defined(__FreeBSD__) +# include +# include +#elif defined(__OpenBSD__) +# include +#endif + +namespace bee::sys { +#if defined(__FreeBSD__) + path_expected exe_path() noexcept { + int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + char exe[1024]; + size_t length = 1024; + int error = sysctl(name, 4, exe, &length, NULL, 0); + if (error < 0 || length <= 1) { + return unexpected(error::sys_errmsg("exe_path")); + } + return fs::path(exe, exe + length - 1); + } +#elif defined(__OpenBSD__) + path_expected exe_path() noexcept { + int name[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; + size_t argc; + if (sysctl(name, 4, NULL, &argc, NULL, 0) < 0) { + return unexpected(error::sys_errmsg("exe_path")); + } + const char** argv = (const char**)malloc(argc); + if (!argv) { + return unexpected(error::sys_errmsg("exe_path")); + } + if (sysctl(name, 4, argv, &argc, NULL, 0) < 0) { + return unexpected(error::sys_errmsg("exe_path")); + } + return fs::path(argv[0]); + } +#else + path_expected exe_path() noexcept { + std::error_code ec; + auto res = fs::read_symlink("/proc/self/exe", ec); + if (ec) { + return unexpected(error::sys_errmsg("exe_path")); + } + return res; + } +#endif +} diff --git a/bee/sys/path_helper.cpp b/bee/sys/path_helper.cpp deleted file mode 100644 index 003138e9..00000000 --- a/bee/sys/path_helper.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include -#include -#include - -#if defined(_WIN32) - -# include -# include - -// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx -extern "C" IMAGE_DOS_HEADER __ImageBase; - -namespace bee::path_helper { - static path_expected dll_path(HMODULE module_handle) noexcept { - wchar_t buffer[MAX_PATH]; - DWORD path_len = ::GetModuleFileNameW(module_handle, buffer, _countof(buffer)); - if (path_len == 0) { - return unexpected(error::sys_errmsg("GetModuleFileNameW")); - } - if (path_len < _countof(buffer)) { - return fs::path(buffer, buffer + path_len); - } - for (DWORD buf_len = 0x200; buf_len <= 0x10000; buf_len <<= 1) { - dynarray buf(buf_len); - path_len = ::GetModuleFileNameW(module_handle, buf.data(), buf_len); - if (path_len == 0) { - return unexpected(error::sys_errmsg("GetModuleFileNameW")); - } - if (path_len < _countof(buffer)) { - return fs::path(buf.data(), buf.data() + path_len); - } - } - return unexpected("::GetModuleFileNameW return too long."); - } - - path_expected exe_path() noexcept { - return dll_path(NULL); - } - - path_expected dll_path() noexcept { - return dll_path(reinterpret_cast(&__ImageBase)); - } -} - -#else - -# if defined(__APPLE__) - -# include - -namespace bee::path_helper { - path_expected exe_path() noexcept { - uint32_t path_len = 0; - _NSGetExecutablePath(0, &path_len); - if (path_len <= 1) { - return unexpected("_NSGetExecutablePath failed."); - } - dynarray buf(path_len); - int rv = _NSGetExecutablePath(buf.data(), &path_len); - if (rv != 0) { - return unexpected("_NSGetExecutablePath failed."); - } - return fs::path(buf.data(), buf.data() + path_len - 1); - } -} - -# else - -# include - -# if defined(__FreeBSD__) -# include -# include -# elif defined(__OpenBSD__) -# include -# include -# endif - -namespace bee::path_helper { - path_expected exe_path() noexcept { -# if defined(__FreeBSD__) - int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; - char exe[1024]; - size_t length = 1024; - int error = sysctl(name, 4, exe, &length, NULL, 0); - if (error < 0 || length <= 1) { - return unexpected(error::sys_errmsg("exe_path")); - } - return fs::path(exe, exe + length - 1); -# elif defined(__OpenBSD__) - int name[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; - size_t argc; - if (sysctl(name, 4, NULL, &argc, NULL, 0) < 0) { - return unexpected(error::sys_errmsg("exe_path")); - } - const char** argv = (const char**)malloc(argc); - if (!argv) { - return unexpected(error::sys_errmsg("exe_path")); - } - if (sysctl(name, 4, argv, &argc, NULL, 0) < 0) { - return unexpected(error::sys_errmsg("exe_path")); - } - return fs::path(argv[0]); -# else - std::error_code ec; - auto res = fs::read_symlink("/proc/self/exe", ec); - if (ec) { - return unexpected(error::sys_errmsg("exe_path")); - } - return res; -# endif - } -} - -# endif - -# include - -namespace bee::path_helper { - static path_expected dll_path(void* module_handle) noexcept { - ::Dl_info dl_info; - dl_info.dli_fname = 0; - const int ret = ::dladdr(module_handle, &dl_info); - if (0 != ret && dl_info.dli_fname != NULL) { - std::error_code ec; - auto path = fs::absolute(dl_info.dli_fname, ec); - if (ec) { - return unexpected(ec.message()); - } - return path.lexically_normal(); - } - return unexpected("::dladdr failed."); - } - - path_expected dll_path() noexcept { - return dll_path((void*)&exe_path); - } -} - -#endif diff --git a/bee/sys/path_linux.cpp b/bee/sys/path_linux.cpp new file mode 100644 index 00000000..f18a8639 --- /dev/null +++ b/bee/sys/path_linux.cpp @@ -0,0 +1,14 @@ +#include +#include +#include + +namespace bee::sys { + path_expected exe_path() noexcept { + std::error_code ec; + auto res = fs::read_symlink("/proc/self/exe", ec); + if (ec) { + return unexpected(error::sys_errmsg("exe_path")); + } + return res; + } +} diff --git a/bee/sys/path_osx.cpp b/bee/sys/path_osx.cpp new file mode 100644 index 00000000..bf9c7e2e --- /dev/null +++ b/bee/sys/path_osx.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + +namespace bee::sys { + path_expected exe_path() noexcept { + uint32_t path_len = 0; + _NSGetExecutablePath(0, &path_len); + if (path_len <= 1) { + return unexpected("_NSGetExecutablePath failed."); + } + dynarray buf(path_len); + int rv = _NSGetExecutablePath(buf.data(), &path_len); + if (rv != 0) { + return unexpected("_NSGetExecutablePath failed."); + } + return fs::path(buf.data(), buf.data() + path_len - 1); + } +} diff --git a/bee/sys/path_posix.cpp b/bee/sys/path_posix.cpp new file mode 100644 index 00000000..1f4268ab --- /dev/null +++ b/bee/sys/path_posix.cpp @@ -0,0 +1,23 @@ +#include +#include + +namespace bee::sys { + static path_expected dll_path(void* module_handle) noexcept { + ::Dl_info dl_info; + dl_info.dli_fname = 0; + const int ret = ::dladdr(module_handle, &dl_info); + if (0 != ret && dl_info.dli_fname != NULL) { + std::error_code ec; + auto path = fs::absolute(dl_info.dli_fname, ec); + if (ec) { + return unexpected(ec.message()); + } + return path.lexically_normal(); + } + return unexpected("::dladdr failed."); + } + + path_expected dll_path() noexcept { + return dll_path((void*)&exe_path); + } +} diff --git a/bee/sys/path_win.cpp b/bee/sys/path_win.cpp new file mode 100644 index 00000000..37f4e24f --- /dev/null +++ b/bee/sys/path_win.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx +extern "C" IMAGE_DOS_HEADER __ImageBase; + +namespace bee::sys { + static path_expected dll_path(HMODULE module_handle) noexcept { + wchar_t buffer[MAX_PATH]; + DWORD path_len = ::GetModuleFileNameW(module_handle, buffer, _countof(buffer)); + if (path_len == 0) { + return unexpected(error::sys_errmsg("GetModuleFileNameW")); + } + if (path_len < _countof(buffer)) { + return fs::path(buffer, buffer + path_len); + } + for (DWORD buf_len = 0x200; buf_len <= 0x10000; buf_len <<= 1) { + dynarray buf(buf_len); + path_len = ::GetModuleFileNameW(module_handle, buf.data(), buf_len); + if (path_len == 0) { + return unexpected(error::sys_errmsg("GetModuleFileNameW")); + } + if (path_len < _countof(buffer)) { + return fs::path(buf.data(), buf.data() + path_len); + } + } + return unexpected("::GetModuleFileNameW return too long."); + } + + path_expected exe_path() noexcept { + return dll_path(NULL); + } + + path_expected dll_path() noexcept { + return dll_path(reinterpret_cast(&__ImageBase)); + } +} diff --git a/binding/lua_filesystem.cpp b/binding/lua_filesystem.cpp index 28385bd4..5907993d 100644 --- a/binding/lua_filesystem.cpp +++ b/binding/lua_filesystem.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -932,7 +932,7 @@ namespace bee::lua_filesystem { } static int exe_path(lua_State* L) { - auto r = path_helper::exe_path(); + auto r = sys::exe_path(); if (!r) { return lua::push_error(L, r.error()); } @@ -941,7 +941,7 @@ namespace bee::lua_filesystem { } static int dll_path(lua_State* L) { - auto r = path_helper::dll_path(); + auto r = sys::dll_path(); if (!r) { return lua::push_error(L, r.error()); } diff --git a/bootstrap/main.cpp b/bootstrap/main.cpp index 573e95d6..434b8fbd 100644 --- a/bootstrap/main.cpp +++ b/bootstrap/main.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -136,7 +136,7 @@ static int pushargs(lua_State *L) { } static fs::path getprogdir(lua_State *L) { - auto r = bee::path_helper::exe_path(); + auto r = bee::sys::exe_path(); if (!r) { luaL_error(L, "unable to get progdir: %s\n", r.error().c_str()); std::unreachable();