DORMANTno replies

[PATCH] add strcpy_user_path() and use it in init-db.c and git.c

From: Eric Wong <hidden>
Date: 2016-06-15 22:42:15
Subsystem: the rest · Maintainer: Linus Torvalds

strcpy_user_path(dest,src) acts just like strcpy() except tildes
in src are expanded appropriately to point to a user's home
directory.

The following expansions are supported:

~user/path	reads home directory from getpwnam()
~/path	 	reads home directory from $HOME env,
		or getpwuid() if $HOME is not set

This patch makes it easier for an ordinary user to share compiled
binaries across different machines, especially if they have different
account names and home directories on those machines.

Hint: build git with: make 'prefix=~'

Signed-off-by: Eric Wong <redacted>

---

 cache.h   |    1 +
 git.c     |    6 ++++++
 init-db.c |    3 ++-
 path.c    |   41 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 50 insertions(+), 1 deletions(-)

c46a17b746572e6d16aa026de50d7911eddf8664
diff --git a/cache.h b/cache.h
index c5ff4b7..041bf94 100644
--- a/cache.h
+++ b/cache.h
@@ -184,6 +184,7 @@ extern const unsigned char null_sha1[20]
 
 int git_mkstemp(char *path, size_t n, const char *template);
 
+char * strcpy_user_path(char *dest, const char *path);
 int safe_create_leading_directories(char *path);
 char *safe_strncpy(char *, const char *, size_t);
 char *enter_repo(char *path, int strict);
diff --git a/git.c b/git.c
index 434a3d9..15f4c69 100644
--- a/git.c
+++ b/git.c
@@ -12,6 +12,8 @@
 #include <termios.h>
 #include "git-compat-util.h"
 
+extern char * strcpy_user_path(char *dest, const char *path);
+
 #ifndef PATH_MAX
 # define PATH_MAX 4096
 #endif
@@ -234,6 +236,7 @@ int main(int argc, char **argv, char **e
 {
 	char git_command[PATH_MAX + 1];
 	char wd[PATH_MAX + 1];
+	char tmp[PATH_MAX + 1];
 	int i, len, show_help = 0;
 	char *exec_path = getenv("GIT_EXEC_PATH");
 
@@ -269,6 +272,9 @@ int main(int argc, char **argv, char **e
 			cmd_usage(NULL, NULL);
 	}
 
+	strcpy_user_path(tmp, exec_path);
+	exec_path = tmp;
+
 	if (i >= argc || show_help) {
 		if (i >= argc)
 			cmd_usage(exec_path, NULL);
diff --git a/init-db.c b/init-db.c
index ead37b5..468c93a 100644
--- a/init-db.c
+++ b/init-db.c
@@ -119,7 +119,8 @@ static void copy_templates(const char *g
 
 	if (!template_dir)
 		template_dir = DEFAULT_GIT_TEMPLATE_DIR;
-	strcpy(template_path, template_dir);
+	strcpy_user_path(template_path, template_dir);
+	
 	template_len = strlen(template_path);
 	if (template_path[template_len-1] != '/') {
 		template_path[template_len++] = '/';
diff --git a/path.c b/path.c
index 334b2bd..3caa188 100644
--- a/path.c
+++ b/path.c
@@ -131,6 +131,47 @@ int validate_symref(const char *path)
 	return -1;
 }
 
+char * strcpy_user_path(char *dest, const char *path)
+{
+	if (path[0] == '~') {
+		struct passwd *pw;
+
+		if (path[1] == '/' || path[1] == '\0') {
+			char *home;
+			
+			if (!(home = getenv("HOME"))) {
+				pw = getpwuid(getuid());
+				if (pw && pw->pw_dir)
+					home = pw->pw_dir;
+			}
+				
+			strcpy(dest, home);
+			
+			if (path[1] == '/')
+				strcat(dest, path + 1);
+		} else {
+			char *slash;
+			
+			if ((slash = strchr(path,'/'))) {
+				memcpy(pathname, path + 1, slash - path - 1);
+				pathname[slash - path] = '\0';
+				pw = getpwnam(pathname);
+			} else
+				pw = getpwnam(path + 1);
+
+			if (pw && pw->pw_dir) {
+				strcpy(dest, pw->pw_dir);
+				if (slash)
+					strcat(dest,slash);
+			} else
+				strcpy(dest, path);
+		}
+	} else
+		strcpy(dest, path);
+
+	return dest;
+}
+
 static char *user_path(char *buf, char *path, int sz)
 {
 	struct passwd *pw;
-- 
1.0.GIT
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help