just add the hostname in the path when using --base-path and --user-path. this should be enough for most needs. Signed-off-by: Pierre Habouzit <madcoder@xxxxxxxxxx> --- Here is a proposal for daemon side virtualhosting support. This is quite simple, and just uses the hostname in the path where it looks for the git repository. Only works in conjuction of --base-path or --user-path btw. Documentation/git-daemon.txt | 12 +++++++ daemon.c | 73 +++++++++++++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt index 0f7d274..ab5b232 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@ -79,6 +79,18 @@ OPTIONS taken as a request to access `path/foo` repository in the home directory of user `alice`. +--use-vhosts:: + Use git daemon cheap virtual hosting scheme. ++ +Used with --base-path=/foo, it will search the repositories in /foo/HOSTNAME +instead of /foo - if you try to pull git://git.example.com/hello.git, it will +search into /foo/git.example.com/hello.git. ++ +When using --user-path the HOSTNAME is appended to the path as well, so for +--user-path=some/path, request to git://git.example.com/~alice/foo is taken as +a request to access some/path/git.example.com/foo in the home directory of +user `alice`. + --verbose:: Log details about the incoming connections and requested files. diff --git a/daemon.c b/daemon.c index 012936f..146482c 100644 --- a/daemon.c +++ b/daemon.c @@ -17,7 +17,7 @@ static int reuseaddr; static const char daemon_usage[] = "git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n" -" [--timeout=n] [--init-timeout=n] [--strict-paths]\n" +" [--timeout=n] [--init-timeout=n] [--use-vhosts] [--strict-paths]\n" " [--base-path=path] [--user-path | --user-path=path]\n" " [--reuseaddr] [--detach] [--pid-file=file] [directory...]"; @@ -25,6 +25,8 @@ static const char daemon_usage[] = static char **ok_paths; static int strict_paths; +static int use_vhosts; + /* If this is set, git-daemon-export-ok is not required */ static int export_all_trees; @@ -148,7 +150,7 @@ static int avoid_alias(char *p) } } -static char *path_ok(char *dir) +static char *path_ok(char *dir, char *vhost) { static char rpath[PATH_MAX]; char *path; @@ -158,6 +160,11 @@ static char *path_ok(char *dir) return NULL; } + if (use_vhosts && !vhost) { + logerror("using virtual hosting, and not host= was specified !"); + return NULL; + } + if (*dir == '~') { if (!user_path) { logerror("'%s': User-path not allowed", dir); @@ -174,9 +181,25 @@ static char *path_ok(char *dir) slash = dir + restlen; namlen = slash - dir; restlen -= namlen; - loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash); - snprintf(rpath, PATH_MAX, "%.*s/%s%.*s", - namlen, dir, user_path, restlen, slash); + + if (use_vhosts) { + loginfo("host <%s>, " + "userpath <%s>, request <%s>, " + "namlen %d, restlen %d, slash <%s>", + vhost, + user_path, dir, + namlen, restlen, slash); + snprintf(rpath, PATH_MAX, "%.*s/%s/%s%.*s", + namlen, dir, user_path, vhost, + restlen, slash); + } else { + loginfo("userpath <%s>, request <%s>, " + "namlen %d, restlen %d, slash <%s>", + user_path, dir, + namlen, restlen, slash); + snprintf(rpath, PATH_MAX, "%.*s/%s%.*s", + namlen, dir, user_path, restlen, slash); + } dir = rpath; } } @@ -187,7 +210,11 @@ static char *path_ok(char *dir) return NULL; } else { - snprintf(rpath, PATH_MAX, "%s%s", base_path, dir); + if (use_vhosts) { + snprintf(rpath, PATH_MAX, "%s/%s%s", base_path, vhost, dir); + } else { + snprintf(rpath, PATH_MAX, "%s%s", base_path, dir); + } dir = rpath; } } @@ -229,15 +256,19 @@ static char *path_ok(char *dir) return NULL; /* Fallthrough. Deny by default */ } -static int upload(char *dir) +static int upload(char *dir, char *vhost) { /* Timeout as string */ char timeout_buf[64]; const char *path; - loginfo("Request for '%s'", dir); + if (vhost) { + loginfo("Request for '%s' (host = %s)", dir, vhost); + } else { + loginfo("Request for '%s'", dir); + } - if (!(path = path_ok(dir))) + if (!(path = path_ok(dir, vhost))) return -1; /* @@ -274,6 +305,7 @@ static int execute(struct sockaddr *addr { static char line[1000]; int pktlen, len; + char *vhost = NULL; if (addr) { char addrbuf[256] = ""; @@ -303,15 +335,28 @@ #endif alarm(0); len = strlen(line); - if (pktlen != len) + if (pktlen != len) { + int arg_pos = len + 1; + loginfo("Extended attributes (%d bytes) exist <%.*s>", (int) pktlen - len, - (int) pktlen - len, line + len + 1); + (int) pktlen - len, line + arg_pos); + + while (arg_pos < pktlen) { + int arg_len = strlen(line + arg_pos); + + if (!strncmp("host=", line + arg_pos, 5)) { + vhost = line + arg_pos + 5; + } + + arg_pos += arg_len + 1; + } + } if (len && line[len-1] == '\n') line[--len] = 0; if (!strncmp("git-upload-pack ", line, 16)) - return upload(line+16); + return upload(line+16, vhost); logerror("Protocol error: '%s'", line); return -1; @@ -762,6 +807,10 @@ int main(int argc, char **argv) init_timeout = atoi(arg+15); continue; } + if (!strcmp(arg, "--use-vhosts")) { + use_vhosts = 1; + continue; + } if (!strcmp(arg, "--strict-paths")) { strict_paths = 1; continue; -- 1.4.1.1 - 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