X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=connect.c;h=7a6a73f2a333d067c5a5442004f76ebbb9aaed17;hb=68d42c41ef33cde500307660bb64a1c74f62711e;hp=52d709e58d53f053ec00bfb9f31501684cbaf0e5;hpb=c9bc159d7f41e2916830b05529c1ce06a81d975f;p=git.git diff --git a/connect.c b/connect.c index 52d709e58..7a6a73f2a 100644 --- a/connect.c +++ b/connect.c @@ -8,14 +8,44 @@ #include #include #include +#include -static char *server_capabilities = NULL; +static char *server_capabilities; + +static int check_ref(const char *name, int len, unsigned int flags) +{ + if (!flags) + return 1; + + if (len > 45 || memcmp(name, "refs/", 5)) + return 0; + + /* Skip the "refs/" part */ + name += 5; + len -= 5; + + /* REF_NORMAL means that we don't want the magic fake tag refs */ + if ((flags & REF_NORMAL) && check_ref_format(name) < 0) + return 0; + + /* REF_HEADS means that we want regular branch heads */ + if ((flags & REF_HEADS) && !memcmp(name, "heads/", 6)) + return 1; + + /* REF_TAGS means that we want tags */ + if ((flags & REF_TAGS) && !memcmp(name, "tags/", 5)) + return 1; + + /* All type bits clear means that we are ok with anything */ + return !(flags & ~REF_NORMAL); +} /* * Read all the refs from the other end */ struct ref **get_remote_heads(int in, struct ref **list, - int nr_match, char **match, int ignore_funny) + int nr_match, char **match, + unsigned int flags) { *list = NULL; for (;;) { @@ -42,10 +72,8 @@ struct ref **get_remote_heads(int in, struct ref **list, server_capabilities = strdup(name + name_len + 1); } - if (ignore_funny && 45 < len && !memcmp(name, "refs/", 5) && - check_ref_format(name + 5)) + if (!check_ref(name, name_len, flags)) continue; - if (nr_match && !path_match(name, nr_match, match)) continue; ref = xcalloc(1, sizeof(*ref) + len - 40); @@ -327,9 +355,9 @@ static enum protocol get_protocol(const char *name) */ static int git_tcp_connect_sock(char *host) { - int sockfd = -1; + int sockfd = -1, saved_errno = 0; char *colon, *end; - char *port = STR(DEFAULT_GIT_PORT); + const char *port = STR(DEFAULT_GIT_PORT); struct addrinfo hints, *ai0, *ai; int gai; @@ -361,9 +389,12 @@ static int git_tcp_connect_sock(char *host) for (ai0 = ai; ai; ai = ai->ai_next) { sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sockfd < 0) + if (sockfd < 0) { + saved_errno = errno; continue; + } if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { + saved_errno = errno; close(sockfd); sockfd = -1; continue; @@ -374,7 +405,7 @@ static int git_tcp_connect_sock(char *host) freeaddrinfo(ai0); if (sockfd < 0) - die("unable to connect a socket (%s)", strerror(errno)); + die("unable to connect a socket (%s)", strerror(saved_errno)); return sockfd; } @@ -386,7 +417,7 @@ static int git_tcp_connect_sock(char *host) */ static int git_tcp_connect_sock(char *host) { - int sockfd = -1; + int sockfd = -1, saved_errno = 0; char *colon, *end; char *port = STR(DEFAULT_GIT_PORT), *ep; struct hostent *he; @@ -425,8 +456,10 @@ static int git_tcp_connect_sock(char *host) for (ap = he->h_addr_list; *ap; ap++) { sockfd = socket(he->h_addrtype, SOCK_STREAM, 0); - if (sockfd < 0) + if (sockfd < 0) { + saved_errno = errno; continue; + } memset(&sa, 0, sizeof sa); sa.sin_family = he->h_addrtype; @@ -434,6 +467,7 @@ static int git_tcp_connect_sock(char *host) memcpy(&sa.sin_addr, *ap, he->h_length); if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) { + saved_errno = errno; close(sockfd); sockfd = -1; continue; @@ -442,7 +476,7 @@ static int git_tcp_connect_sock(char *host) } if (sockfd < 0) - die("unable to connect a socket (%s)", strerror(errno)); + die("unable to connect a socket (%s)", strerror(saved_errno)); return sockfd; } @@ -450,8 +484,7 @@ static int git_tcp_connect_sock(char *host) #endif /* NO_IPV6 */ -static void git_tcp_connect(int fd[2], - const char *prog, char *host, char *path) +static void git_tcp_connect(int fd[2], char *host) { int sockfd = git_tcp_connect_sock(host); @@ -460,8 +493,8 @@ static void git_tcp_connect(int fd[2], } -static char *git_proxy_command = NULL; -static const char *rhost_name = NULL; +static char *git_proxy_command; +static const char *rhost_name; static int rhost_len; static int git_proxy_command_options(const char *var, const char *value) @@ -521,10 +554,9 @@ static int git_use_proxy(const char *host) return (git_proxy_command && *git_proxy_command); } -static void git_proxy_connect(int fd[2], - const char *prog, char *host, char *path) +static void git_proxy_connect(int fd[2], char *host) { - char *port = STR(DEFAULT_GIT_PORT); + const char *port = STR(DEFAULT_GIT_PORT); char *colon, *end; int pipefd[2][2]; pid_t pid; @@ -581,6 +613,11 @@ int git_connect(int fd[2], char *url, const char *prog) enum protocol protocol = PROTO_LOCAL; int free_path = 0; + /* Without this we cannot rely on waitpid() to tell + * what happened to our children. + */ + signal(SIGCHLD, SIG_DFL); + host = strstr(url, "://"); if(host) { *host = '\0'; @@ -637,9 +674,9 @@ int git_connect(int fd[2], char *url, const char *prog) */ char *target_host = strdup(host); if (git_use_proxy(host)) - git_proxy_connect(fd, prog, host, path); + git_proxy_connect(fd, host); else - git_tcp_connect(fd, prog, host, path); + git_tcp_connect(fd, host); /* * Separate original protocol components prog and path * from extended components with a NUL byte. @@ -700,14 +737,9 @@ int git_connect(int fd[2], char *url, const char *prog) int finish_connect(pid_t pid) { - int ret; - - for (;;) { - ret = waitpid(pid, NULL, 0); - if (!ret) - break; + while (waitpid(pid, NULL, 0) < 0) { if (errno != EINTR) - break; + return -1; } - return ret; + return 0; }