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 <weiser@xxxxxxxxxxxxxxxxxxxx> --- - 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 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html