X-Git-Url: https://git.octo.it/?p=git.git;a=blobdiff_plain;f=connect.c;h=52d709e58d53f053ec00bfb9f31501684cbaf0e5;hp=e1c04e1eaeb5b1d7c86f70fbad1a5167b58c1b17;hb=HEAD;hpb=92643a27cc2cc7ce55ba2afd6155f94b40e1aa89 diff --git a/connect.c b/connect.c index e1c04e1e..52d709e5 100644 --- a/connect.c +++ b/connect.c @@ -1,3 +1,4 @@ +#include "git-compat-util.h" #include "cache.h" #include "pkt-line.h" #include "quote.h" @@ -73,7 +74,7 @@ int get_ack(int fd, unsigned char *result_sha1) line[--len] = 0; if (!strcmp(line, "NAK")) return 0; - if (!strncmp(line, "ACK ", 3)) { + if (!strncmp(line, "ACK ", 4)) { if (!get_sha1_hex(line+4, result_sha1)) { if (strstr(line+45, "continue")) return 2; @@ -99,7 +100,7 @@ int path_match(const char *path, int nr, char **match) if (pathlen > len && path[pathlen - len - 1] != '/') continue; *s = 0; - return 1; + return (i + 1); } return 0; } @@ -321,7 +322,10 @@ static enum protocol get_protocol(const char *name) #ifndef NO_IPV6 -static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) +/* + * Returns a connected socket() fd, or else die()s. + */ +static int git_tcp_connect_sock(char *host) { int sockfd = -1; char *colon, *end; @@ -355,7 +359,8 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) die("Unable to look up %s (%s)", host, gai_strerror(gai)); for (ai0 = ai; ai; ai = ai->ai_next) { - sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + sockfd = socket(ai->ai_family, + ai->ai_socktype, ai->ai_protocol); if (sockfd < 0) continue; if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { @@ -371,15 +376,15 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) if (sockfd < 0) die("unable to connect a socket (%s)", strerror(errno)); - fd[0] = sockfd; - fd[1] = sockfd; - packet_write(sockfd, "%s %s\n", prog, path); - return 0; + return sockfd; } #else /* NO_IPV6 */ -static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) +/* + * Returns a connected socket() fd, or else die()s. + */ +static int git_tcp_connect_sock(char *host) { int sockfd = -1; char *colon, *end; @@ -406,7 +411,6 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) port = colon + 1; } - he = gethostbyname(host); if (!he) die("Unable to look up %s (%s)", host, hstrerror(h_errno)); @@ -440,13 +444,21 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) if (sockfd < 0) die("unable to connect a socket (%s)", strerror(errno)); + return sockfd; +} + +#endif /* NO_IPV6 */ + + +static void git_tcp_connect(int fd[2], + const char *prog, char *host, char *path) +{ + int sockfd = git_tcp_connect_sock(host); + fd[0] = sockfd; fd[1] = sockfd; - packet_write(sockfd, "%s %s\n", prog, path); - return 0; } -#endif /* NO_IPV6 */ static char *git_proxy_command = NULL; static const char *rhost_name = NULL; @@ -509,7 +521,8 @@ static int git_use_proxy(const char *host) return (git_proxy_command && *git_proxy_command); } -static int git_proxy_connect(int fd[2], const char *prog, char *host, char *path) +static void git_proxy_connect(int fd[2], + const char *prog, char *host, char *path) { char *port = STR(DEFAULT_GIT_PORT); char *colon, *end; @@ -546,12 +559,12 @@ static int git_proxy_connect(int fd[2], const char *prog, char *host, char *path execlp(git_proxy_command, git_proxy_command, host, port, NULL); die("exec failed"); } + if (pid < 0) + die("fork failed"); fd[0] = pipefd[0][0]; fd[1] = pipefd[1][1]; close(pipefd[0][1]); close(pipefd[1][0]); - packet_write(fd[1], "%s %s\n", prog, path); - return pid; } /* @@ -566,6 +579,7 @@ int git_connect(int fd[2], char *url, const char *prog) int pipefd[2][2]; pid_t pid; enum protocol protocol = PROTO_LOCAL; + int free_path = 0; host = strstr(url, "://"); if(host) { @@ -609,21 +623,42 @@ int git_connect(int fd[2], char *url, const char *prog) char *ptr = path; if (path[1] == '~') path++; - else + else { path = strdup(ptr); + free_path = 1; + } *ptr = '\0'; } if (protocol == PROTO_GIT) { + /* These underlying connection commands die() if they + * cannot connect. + */ + char *target_host = strdup(host); if (git_use_proxy(host)) - return git_proxy_connect(fd, prog, host, path); - return git_tcp_connect(fd, prog, host, path); + git_proxy_connect(fd, prog, host, path); + else + git_tcp_connect(fd, prog, host, path); + /* + * Separate original protocol components prog and path + * from extended components with a NUL byte. + */ + packet_write(fd[1], + "%s %s%chost=%s%c", + prog, path, 0, + target_host, 0); + free(target_host); + if (free_path) + free(path); + return 0; } if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0) die("unable to create pipe pair for communication"); pid = fork(); + if (pid < 0) + die("unable to fork"); if (!pid) { snprintf(command, sizeof(command), "%s %s", prog, sq_quote(path)); @@ -658,6 +693,8 @@ int git_connect(int fd[2], char *url, const char *prog) fd[1] = pipefd[1][1]; close(pipefd[0][1]); close(pipefd[1][0]); + if (free_path) + free(path); return pid; }