[PATCH] Extend runtime prefix computation
From: Michael Weiser <hidden>
Date: 2016-06-15 22:55:25
Support determining the binaries' installation path at runtime even if called without any path components (i.e. via search path). Implement fallback to compiled-in prefix if determination fails or is impossible. Signed-off-by: Michael Weiser <redacted> --- - Has two very minor memory leaks - function is called only once per program execution. Do we care? Alternative: Use static buffer instead. exec_cmd.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 53 insertions(+), 15 deletions(-)
diff --git a/exec_cmd.c b/exec_cmd.c
index 125fa6f..d50d7f8 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c@@ -4,28 +4,22 @@ #define MAX_ARGS 32 static const char *argv_exec_path; -static const char *argv0_path; +static const char *argv0_path = NULL; const char *system_path(const char *path) { -#ifdef RUNTIME_PREFIX - static const char *prefix; -#else static const char *prefix = PREFIX; -#endif struct strbuf d = STRBUF_INIT; if (is_absolute_path(path)) return path; #ifdef RUNTIME_PREFIX - assert(argv0_path); - assert(is_absolute_path(argv0_path)); - - if (!prefix && - !(prefix = strip_path_suffix(argv0_path, GIT_EXEC_PATH)) && - !(prefix = strip_path_suffix(argv0_path, BINDIR)) && - !(prefix = strip_path_suffix(argv0_path, "git"))) { + if (!argv0_path || + !is_absolute_path(argv0_path) || + (!(prefix = strip_path_suffix(argv0_path, GIT_EXEC_PATH)) && + !(prefix = strip_path_suffix(argv0_path, BINDIR)) && + !(prefix = strip_path_suffix(argv0_path, "git")))) { prefix = PREFIX; trace_printf("RUNTIME_PREFIX requested, " "but prefix computation failed. "
@@ -41,20 +35,64 @@ const char *system_path(const char *path) const char *git_extract_argv0_path(const char *argv0) { const char *slash; + char *abs_argv0 = NULL; if (!argv0 || !*argv0) return NULL; slash = argv0 + strlen(argv0); + /* walk to the first slash from the end */ while (argv0 <= slash && !is_dir_sep(*slash)) slash--; + /* if there was a slash ... */ if (slash >= argv0) { - argv0_path = xstrndup(argv0, slash - argv0); - return slash + 1; + /* ... it's either an absolute path */ + if (is_absolute_path(argv0)) { + /* FIXME: memory leak here */ + argv0_path = xstrndup(argv0, slash - argv0); + return slash + 1; + } + + /* ... or a relative path, in which case we have to make it + * absolute first and do the whole thing again */ + abs_argv0 = xstrdup(real_path(argv0)); + } else { + /* argv0 is no path at all, just a name. Resolve it into a + * path. Unfortunately, this gets system specific. */ +#if defined(__linux__) + struct stat st; + if (!stat("/proc/self/exe", &st)) { + abs_argv0 = xstrdup(real_path("/proc/self/exe")); + } +#elif defined(__APPLE__) + /* Mac OS X has realpath, which incidentally allocates its own + * memory, which in turn is why we do all the xstrdup's in the + * other cases. */ + abs_argv0 = realpath(argv0, NULL); +#endif + + /* if abs_argv0 is still NULL here, something failed above or + * we are on an unsupported system. system_path() will warn + * and fall back to the static prefix */ + if (!abs_argv0) { + argv0_path = NULL; + return argv0; + } } - return argv0; + /* abs_argv0 is an absolute path now for which memory was allocated + * with malloc */ + + slash = abs_argv0 + strlen(abs_argv0); + while (abs_argv0 <= slash && !is_dir_sep(*slash)) + slash--; + + /* FIXME: memory leaks here */ + argv0_path = xstrndup(abs_argv0, slash - abs_argv0); + slash = xstrdup(slash + 1); + free(abs_argv0); + return slash; } void git_set_argv_exec_path(const char *exec_path)
--
1.7.3.4
--
Vorstandsvorsitzender/Chairman of the board of management:
Gerd-Lothar Leonhart
Vorstand/Board of Management:
Dr. Bernd Finkbeiner, Michael Heinrichs,
Dr. Arno Steitz, Dr. Ingrid Zech
Vorsitzender des Aufsichtsrats/
Chairman of the Supervisory Board:
Philippe Miltin
Sitz/Registered Office: Tuebingen
Registergericht/Registration Court: Stuttgart
Registernummer/Commercial Register No.: HRB 382196