All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Introduce a filter-path argument to git-daemon, for doing custom path transformations
@ 2009-03-11 15:17 Johan Sørensen
  2009-03-11 15:58 ` Johannes Sixt
  0 siblings, 1 reply; 14+ messages in thread
From: Johan Sørensen @ 2009-03-11 15:17 UTC (permalink / raw)
  To: git; +Cc: Johan Sørensen

The argument is an executable script that will receive the path to the repos
the client wishes to clone as an argument. It is then the responsibility of the
script to return a zero-terminated string on its stdout with the real path of
the target repository.

This buys us a lot of flexibility when it comes to managing different
repositories, possibly located in many different dirs, but with a uniform
url-structure to the outside world.
---
 Documentation/git-daemon.txt |    7 ++++
 daemon.c                     |   75 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 81 insertions(+), 1 deletions(-)

diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index 36f00ae..1eca344 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -13,6 +13,7 @@ SYNOPSIS
 	     [--strict-paths] [--base-path=path] [--base-path-relaxed]
 	     [--user-path | --user-path=path]
 	     [--interpolated-path=pathtemplate]
+	     [--path-filter=executable]
 	     [--reuseaddr] [--detach] [--pid-file=file]
 	     [--enable=service] [--disable=service]
 	     [--allow-override=service] [--forbid-override=service]
@@ -71,6 +72,12 @@ OPTIONS
 	After interpolation, the path is validated against the directory
 	whitelist.
 
+--path-filter=executable::
+	To support a more flexible directory layout a path filter script 
+	can be used. The executable will receive the requested path from
+	the client as arg0. The executable must return a zero-terminated
+	string on stdout which is the real path 'git-daemon' should serve.
+
 --export-all::
 	Allow pulling from all directories that look like GIT repositories
 	(have the 'objects' and 'refs' subdirectories), even if they
diff --git a/daemon.c b/daemon.c
index d93cf96..b2571df 100644
--- a/daemon.c
+++ b/daemon.c
@@ -22,6 +22,7 @@ static const char daemon_usage[] =
 "           [--strict-paths] [--base-path=path] [--base-path-relaxed]\n"
 "           [--user-path | --user-path=path]\n"
 "           [--interpolated-path=path]\n"
+"           [--path-filter=path]\n"
 "           [--reuseaddr] [--detach] [--pid-file=file]\n"
 "           [--[enable|disable|allow-override|forbid-override]=service]\n"
 "           [--inetd | [--listen=host_or_ipaddr] [--port=n]\n"
@@ -58,6 +59,10 @@ static char *canon_hostname;
 static char *ip_address;
 static char *tcp_port;
 
+/* if defined, the script will be executed with the requested path on stdin
+ * and _must_ return with a successful exitcode and the new path on stdout */
+static char *path_filter_script;
+
 static void logreport(int priority, const char *err, va_list params)
 {
 	if (log_syslog) {
@@ -287,9 +292,62 @@ static int git_daemon_config(const char *var, const char *value, void *cb)
 	return 0;
 }
 
+static char *run_path_filter_script(char *requested_dir) {
+	pid_t pid;
+	char result[256]; /* arbitary */
+	char *real_path;
+	int pipe_out[2];
+	int exit_code = 1;
+
+	pipe(pipe_out);
+
+	loginfo("Executing path filter script: '%s %s'", path_filter_script, requested_dir);
+
+	switch ((pid = fork())) {
+		case -1:
+			logerror("path filter script fork() failed: %s", strerror(errno));
+			return NULL;
+		case 0:
+		close(pipe_out[0]);
+		dup2(pipe_out[1], 1);
+		close(pipe_out[1]);
+
+		execl(path_filter_script, path_filter_script, requested_dir, NULL);
+
+		/* execl failed if we got here */
+		logerror("path filter script execl() failed: %s", strerror(errno));
+		return NULL;
+	default:
+		close(pipe_out[1]);
+	
+		while(waitpid(pid, &exit_code, 0) < 0) {
+			switch(errno) {
+			case EINTR:
+			continue;
+			default:
+				logerror("path filter script waitpid() fail: %s", strerror(errno));
+				goto waitpid_error;
+			}
+		}
+		if (WIFEXITED(exit_code) && WEXITSTATUS(exit_code) == 0) {
+			read(pipe_out[0], result, sizeof(result) - 1);
+			loginfo("path filter script result: %s", result);
+		}
+		waitpid_error:
+		close(pipe_out[0]);
+	}
+
+	if (result) {
+		real_path = result;
+		return real_path;
+	}
+	return NULL;
+}
+
 static int run_service(char *dir, struct daemon_service *service)
 {
 	const char *path;
+	char *real_dir;
 	int enabled = service->enabled;
 
 	loginfo("Request %s for '%s'", service->name, dir);
@@ -299,8 +357,19 @@ static int run_service(char *dir, struct daemon_service *service)
 		errno = EACCES;
 		return -1;
 	}
+	loginfo("path_filter_script %s", path_filter_script);
+	if (!path_filter_script) {
+		real_dir = dir;
+	} else {
+		char *tdir;
+		if ((tdir = run_path_filter_script(dir))) {
+			real_dir = tdir;
+		} else {
+			real_dir = dir;
+		}
+	}
 
-	if (!(path = path_ok(dir)))
+	if (!(path = path_ok(real_dir)))
 		return -1;
 
 	/*
@@ -1018,6 +1087,10 @@ int main(int argc, char **argv)
 			pid_file = arg + 11;
 			continue;
 		}
+		if (!prefixcmp(arg, "--path-filter=")) {
+			path_filter_script = arg + 14;
+			continue;
+		}
 		if (!strcmp(arg, "--detach")) {
 			detach = 1;
 			log_syslog = 1;
-- 
1.6.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2009-03-20 22:29 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-11 15:17 [PATCH] Introduce a filter-path argument to git-daemon, for doing custom path transformations Johan Sørensen
2009-03-11 15:58 ` Johannes Sixt
2009-03-12 10:13   ` Johan Sørensen
2009-03-12 11:29     ` Johannes Schindelin
2009-03-12 15:48       ` Johan Sørensen
2009-03-12 16:50         ` Johannes Schindelin
2009-03-12 19:06       ` Johan Sørensen
2009-03-14  6:58         ` Junio C Hamano
2009-03-14 14:39           ` Johan Sørensen
2009-03-14 18:23             ` Junio C Hamano
2009-03-19  0:15               ` Johannes Schindelin
2009-03-19 13:02                 ` Johan Sørensen
2009-03-20 22:27                   ` Johannes Schindelin
2009-03-12 10:26   ` Johan Sørensen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.