From 97cf70148695df87154ad9fabb312037021a0d82 Mon Sep 17 00:00:00 2001 From: hasufell Date: Mon, 24 Nov 2014 21:20:43 +0100 Subject: [PATCH] Query /proc for the executable path on Linux Author: leper http://trac.wildfiregames.com/ticket/2086 http://trac.wildfiregames.com/changeset/15996 --- source/lib/sysdep/os/bsd/bsd.cpp | 46 +------------- source/lib/sysdep/os/linux/linux.cpp | 62 +++++++----------- .../sysdep/os/unix/unix_executable_pathname.cpp | 73 ++++++++++++++++++++++ .../lib/sysdep/os/unix/unix_executable_pathname.h | 28 +++++++++ 4 files changed, 124 insertions(+), 85 deletions(-) create mode 100644 source/lib/sysdep/os/unix/unix_executable_pathname.cpp create mode 100644 source/lib/sysdep/os/unix/unix_executable_pathname.h diff --git a/source/lib/sysdep/os/bsd/bsd.cpp b/source/lib/sysdep/os/bsd/bsd.cpp index 34e1460..aa74b98 100644 --- a/source/lib/sysdep/os/bsd/bsd.cpp +++ b/source/lib/sysdep/os/bsd/bsd.cpp @@ -23,51 +23,9 @@ #include "precompiled.h" #include "lib/sysdep/sysdep.h" - -#define GNU_SOURCE -#include "mocks/dlfcn.h" -#include "mocks/unistd.h" - -#include +#include "lib/sysdep/os/unix/unix_excecutable_pathname.h" OsPath sys_ExecutablePathname() { - // Find the executable's filename - Dl_info dl_info; - memset(&dl_info, 0, sizeof(dl_info)); - if (!T::dladdr((void *)sys_ExecutablePathname, &dl_info) || !dl_info.dli_fname) - return OsPath(); - const char* path = dl_info.dli_fname; - - // If this looks like an absolute path, use realpath to get the normalized - // path (with no '.' or '..') - if (path[0] == '/') - { - char resolved[PATH_MAX]; - if (!realpath(path, resolved)) - return OsPath(); - return resolved; - } - - // If this looks like a relative path, resolve against cwd and use realpath - if (strchr(path, '/')) - { - char cwd[PATH_MAX]; - if (!T::getcwd(cwd, PATH_MAX)) - return OsPath(); - - char absolute[PATH_MAX]; - int ret = snprintf(absolute, PATH_MAX, "%s/%s", cwd, path); - if (ret < 0 || ret >= PATH_MAX) - return OsPath(); // path too long, or other error - char resolved[PATH_MAX]; - if (!realpath(absolute, resolved)) - return OsPath(); - return resolved; - } - - // If it's not a path at all, i.e. it's just a filename, we'd - // probably have to search through PATH to find it. - // That's complex and should be uncommon, so don't bother. - return OsPath(); + return unix_ExecutablePathname(); } diff --git a/source/lib/sysdep/os/linux/linux.cpp b/source/lib/sysdep/os/linux/linux.cpp index da2a8ac..d2d47af 100644 --- a/source/lib/sysdep/os/linux/linux.cpp +++ b/source/lib/sysdep/os/linux/linux.cpp @@ -23,51 +23,31 @@ #include "precompiled.h" #include "lib/sysdep/sysdep.h" +#include "lib/sysdep/os/unix/unix_executable_pathname.h" -#define GNU_SOURCE -#include "mocks/dlfcn.h" -#include "mocks/unistd.h" - -#include - -OsPath sys_ExecutablePathname() +static bool getPathFromProc(char* buffer, size_t length) { - // Find the executable's filename - Dl_info dl_info; - memset(&dl_info, 0, sizeof(dl_info)); - if (!T::dladdr((void *)sys_ExecutablePathname, &dl_info) || !dl_info.dli_fname) - return OsPath(); - const char* path = dl_info.dli_fname; + int pos = readlink("/proc/self/exe", buffer, length-1); + if (pos <= 0) + return false; + buffer[pos] = '\0'; - // If this looks like an absolute path, use realpath to get the normalized - // path (with no '.' or '..') - if (path[0] == '/') - { - char resolved[PATH_MAX]; - if (!realpath(path, resolved)) - return OsPath(); - return resolved; - } + char* endOfPath = strrchr(buffer, '/'); + if (endOfPath == NULL) + return false; - // If this looks like a relative path, resolve against cwd and use realpath - if (strchr(path, '/')) - { - char cwd[PATH_MAX]; - if (!T::getcwd(cwd, PATH_MAX)) - return OsPath(); + ++endOfPath; + *endOfPath = '\0'; - char absolute[PATH_MAX]; - int ret = snprintf(absolute, PATH_MAX, "%s/%s", cwd, path); - if (ret < 0 || ret >= PATH_MAX) - return OsPath(); // path too long, or other error - char resolved[PATH_MAX]; - if (!realpath(absolute, resolved)) - return OsPath(); - return resolved; - } + return true; +} + +OsPath sys_ExecutablePathname() +{ + // Check /proc for the path + char pathBuffer[PATH_MAX]; + if (getPathFromProc(pathBuffer, sizeof(pathBuffer))) + return pathBuffer; - // If it's not a path at all, i.e. it's just a filename, we'd - // probably have to search through PATH to find it. - // That's complex and should be uncommon, so don't bother. - return OsPath(); + return unix_ExecutablePathname(); } diff --git a/source/lib/sysdep/os/unix/unix_executable_pathname.cpp b/source/lib/sysdep/os/unix/unix_executable_pathname.cpp new file mode 100644 index 0000000..ae7b989 --- /dev/null +++ b/source/lib/sysdep/os/unix/unix_executable_pathname.cpp @@ -0,0 +1,73 @@ +/* Copyright (c) 2014 Wildfire Games + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS 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 + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "precompiled.h" + +#include "lib/sysdep/sysdep.h" + +#define GNU_SOURCE +#include "mocks/dlfcn.h" +#include "mocks/unistd.h" + +#include + +OsPath unix_ExecutablePathname() +{ + // Find the executable's filename + Dl_info dl_info; + memset(&dl_info, 0, sizeof(dl_info)); + if (!T::dladdr((void *)sys_ExecutablePathname, &dl_info) || !dl_info.dli_fname) + return OsPath(); + const char* path = dl_info.dli_fname; + + // If this looks like an absolute path, use realpath to get the normalized + // path (with no '.' or '..') + if (path[0] == '/') + { + char resolved[PATH_MAX]; + if (!realpath(path, resolved)) + return OsPath(); + return resolved; + } + + // If this looks like a relative path, resolve against cwd and use realpath + if (strchr(path, '/')) + { + char cwd[PATH_MAX]; + if (!T::getcwd(cwd, PATH_MAX)) + return OsPath(); + + char absolute[PATH_MAX]; + int ret = snprintf(absolute, PATH_MAX, "%s/%s", cwd, path); + if (ret < 0 || ret >= PATH_MAX) + return OsPath(); // path too long, or other error + char resolved[PATH_MAX]; + if (!realpath(absolute, resolved)) + return OsPath(); + return resolved; + } + + // If it's not a path at all, i.e. it's just a filename, we'd + // probably have to search through PATH to find it. + // That's complex and should be uncommon, so don't bother. + return OsPath(); +} diff --git a/source/lib/sysdep/os/unix/unix_executable_pathname.h b/source/lib/sysdep/os/unix/unix_executable_pathname.h new file mode 100644 index 0000000..f87c340 --- /dev/null +++ b/source/lib/sysdep/os/unix/unix_executable_pathname.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2014 Wildfire Games + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS 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 + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef INCLUDED_UNIX_EXECUTABLE_PATHNAME +#define INCLUDED_UNIX_EXECUTABLE_PATHNAME + +OsPath unix_ExecutablePathname(); + +#endif // INCLUDED_UNIX_EXECUTABLE_PATHNAME -- 2.1.3