git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] Extend runtime prefix computation

From
MWMichael Weiser <michael.weiser@gmx.de>
Date
Apr 15, 2016, 14:30 UTC
Message-ID
<20160415143001.GA67437@dinsnail.net>

Make git fully relocatable at runtime extending the runtime prefix calculation. Handle absolute and relative paths in argv0. Handle no path at all in argv0 in a system-specific manner. Replace assertions with initialised variables and checks that lead to fallback to the static prefix. ---

Notes:
    Tested-by: David Abdurachmanov <David.Abdurachmanov@cern.ch>
    Pull-Request: https://github.com/git/git/pull/224
 exec_cmd.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 58 insertions(+), 14 deletions(-)
diff --git a/exec_cmd.c b/exec_cmd.c
index 9d5703a..f0db070 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -3,30 +3,27 @@
 #include "quote.h"
 #include "argv-array.h"
 #define MAX_ARGS	32
+#if defined(__APPLE__)
+#include <mach-o/dyld.h>
+#endif
 
 static const char *argv_exec_path;
 static const char *argv0_path;
 
 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 xstrdup(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,6 +38,8 @@ char *system_path(const char *path)
 const char *git_extract_argv0_path(const char *argv0)
 {
 	const char *slash;
+	char *to_resolve = NULL;
+	const char *resolved;
 
 	if (!argv0 || !*argv0)
 		return NULL;
@@ -48,11 +47,56 @@ const char *git_extract_argv0_path(const char *argv0)
 	slash = find_last_dir_sep(argv0);
 
 	if (slash) {
-		argv0_path = xstrndup(argv0, slash - argv0);
-		return slash + 1;
+		/* ... it's either an absolute path */
+		if (is_absolute_path(argv0)) {
+			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 */
+		to_resolve = xstrdup(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))
+			to_resolve = xstrdup("/proc/self/exe");
+#elif defined(__APPLE__)
+		/* call with len == 0 queries the necessary buffer size */
+		uint32_t len = 0;
+		if(_NSGetExecutablePath(NULL, &len) != 0) {
+			to_resolve = malloc(len);
+			if (to_resolve) {
+				/* get the executable path now we have a buffer
+				 * of proper size */
+				if(_NSGetExecutablePath(to_resolve, &len) != 0) {
+					free(to_resolve);
+					return argv0;
+				}
+			}
+		}
+#endif
+
+		/* if to_resolve 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 (!to_resolve)
+			return argv0;
 	}
 
-	return argv0;
+	/* resolve path from absolute to canonical */
+	resolved = real_path(to_resolve);
+	free(to_resolve);
+
+	slash = find_last_dir_sep(resolved);
+	if (!slash)
+		return argv0;
+
+	argv0_path = xstrndup(resolved, slash - resolved);
+	slash = xstrdup(slash + 1);
+	return slash;
 }
 
 void git_set_argv_exec_path(const char *exec_path)
-- 
2.6.4 (Apple Git-63)
Next: Junio C Hamano
Message 1 of 4 in “Extend runtime prefix computation”
  1. Extend runtime prefix computationMichael Weiser, Apr 15, 2016
  2. Junio C HamanoApr 15, 2016
  3. Johannes SchindelinApr 18, 2016
  4. Michael WeiserApr 20, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.