diff --git a/src/netops.c b/src/netops.c index 54aaa4677..7d8a7b28c 100644 --- a/src/netops.c +++ b/src/netops.c @@ -77,7 +77,7 @@ int gitno_connect(const char *host, const char *port) struct addrinfo *info, *p; struct addrinfo hints; int ret, error = GIT_SUCCESS; - int s; + GIT_SOCKET s; memset(&hints, 0x0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; @@ -92,7 +92,11 @@ int gitno_connect(const char *host, const char *port) for (p = info; p != NULL; p = p->ai_next) { s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); +#ifdef GIT_WIN32 + if (s == INVALID_SOCKET) { +#else if (s < 0) { +#endif error = GIT_EOSERR; goto cleanup; } @@ -109,19 +113,21 @@ int gitno_connect(const char *host, const char *port) } /* Oops, we couldn't connect to any address */ - error = GIT_EOSERR; + error = git__throw(GIT_EOSERR, "Failed to connect: %s", strerror(errno)); cleanup: freeaddrinfo(info); return error; } -int gitno_send(int s, const char *msg, size_t len, int flags) +int gitno_send(GIT_SOCKET s, const char *msg, size_t len, int flags) { int ret; size_t off = 0; while (off < len) { + errno = 0; + ret = send(s, msg + off, len - off, flags); if (ret < 0) return git__throw(GIT_EOSERR, "Error sending data: %s", strerror(errno)); @@ -132,6 +138,18 @@ int gitno_send(int s, const char *msg, size_t len, int flags) return off; } +#ifdef GIT_WIN32 +int gitno_close(GIT_SOCKET s) +{ + return closesocket(s) == SOCKET_ERROR ? -1 : 0; +} +#else +int gitno_close(GIT_SOCKET s) +{ + return close(s); +} +#endif + int gitno_select_in(gitno_buffer *buf, long int sec, long int usec) { fd_set fds; diff --git a/src/netops.h b/src/netops.h index 0d962ef61..203df85af 100644 --- a/src/netops.h +++ b/src/netops.h @@ -10,7 +10,7 @@ #ifndef GIT_WIN32 typedef int GIT_SOCKET; #else -typedef unsigned int GIT_SOCKET; +typedef SOCKET GIT_SOCKET; #endif typedef struct gitno_buffer { @@ -26,7 +26,8 @@ void gitno_consume(gitno_buffer *buf, const char *ptr); void gitno_consume_n(gitno_buffer *buf, size_t cons); int gitno_connect(const char *host, const char *port); -int gitno_send(int s, const char *msg, size_t len, int flags); +int gitno_send(GIT_SOCKET s, const char *msg, size_t len, int flags); +int gitno_close(GIT_SOCKET s); int gitno_select_in(gitno_buffer *buf, long int sec, long int usec); int gitno_extract_host_and_port(char **host, char **port, const char *url, const char *default_port); diff --git a/src/transport-http.c b/src/transport-http.c index 70086adea..1da56e11f 100644 --- a/src/transport-http.c +++ b/src/transport-http.c @@ -52,6 +52,9 @@ typedef struct { enum last_cb last_cb; char *content_type; char *service; +#ifdef GIT_WIN32 + WSADATA wsd; +#endif } transport_http; static int gen_request(git_buf *buf, const char *url, const char *host, const char *service) @@ -76,7 +79,8 @@ static int gen_request(git_buf *buf, const char *url, const char *host, const ch static int do_connect(transport_http *t, const char *service) { git_buf request = GIT_BUF_INIT; - int s = -1, error; + int error; + int s; const char *url, *prefix; char *host = NULL, *port = NULL; @@ -358,10 +362,14 @@ static int http_close(git_transport *transport) transport_http *t = (transport_http *) transport; int error; - error = close(t->socket); + error = gitno_close(t->socket); if (error < 0) return git__throw(GIT_EOSERR, "Failed to close the socket: %s", strerror(errno)); +#ifdef GIT_WIN32 + WSACleanup(); +#endif + return GIT_SUCCESS; } @@ -388,6 +396,9 @@ static void http_free(git_transport *transport) int git_transport_http(git_transport **out) { transport_http *t; +#ifdef GIT_WIN32 + int ret; +#endif t = git__malloc(sizeof(transport_http)); if (t == NULL) @@ -402,5 +413,13 @@ int git_transport_http(git_transport **out) *out = (git_transport *) t; +#ifdef GIT_WIN32 + ret = WSAStartup(MAKEWORD(2,2), &t->wsd); + if (ret != 0) { + http_free(*out); + return git__throw(GIT_EOSERR, "Winsock init failed"); + } +#endif + return GIT_SUCCESS; } diff --git a/src/transport_git.c b/src/transport_git.c index bcc612b43..8529fd47a 100644 --- a/src/transport_git.c +++ b/src/transport_git.c @@ -22,10 +22,13 @@ typedef struct { git_transport parent; - int socket; + GIT_SOCKET socket; git_vector refs; git_remote_head **heads; git_transport_caps caps; +#ifdef GIT_WIN32 + WSADATA wsd; +#endif } transport_git; /* @@ -35,10 +38,11 @@ typedef struct { */ static int gen_proto(char **out, int *outlen, const char *cmd, const char *url) { - char *delim, *repo, *ptr; + char *delim, *repo; char default_command[] = "git-upload-pack"; char host[] = "host="; int len; + git_buf buf = GIT_BUF_INIT; delim = strchr(url, '/'); if (delim == NULL) @@ -53,22 +57,21 @@ static int gen_proto(char **out, int *outlen, const char *cmd, const char *url) if (cmd == NULL) cmd = default_command; - len = 4 + strlen(cmd) + 1 + strlen(repo) + 1 + strlen(host) + (delim - url) + 2; + len = 4 + strlen(cmd) + 1 + strlen(repo) + 1 + strlen(host) + (delim - url) + 1 + 1; - *out = git__malloc(len); - if (*out == NULL) - return GIT_ENOMEM; + git_buf_grow(&buf, len); - *outlen = len - 1; - ptr = *out; - memset(ptr, 0x0, len); - /* We expect the return value to be > len - 1 so don't bother checking it */ - snprintf(ptr, len -1, "%04x%s %s%c%s%s", len - 1, cmd, repo, 0, host, url); + git_buf_printf(&buf, "%04x%s %s%c%s", len, cmd, repo, 0, host); + git_buf_put(&buf, url, delim - url); + git_buf_putc(&buf, '\0'); + + *outlen = len; + *out = buf.ptr; return GIT_SUCCESS; } -static int send_request(int s, const char *cmd, const char *url) +static int send_request(GIT_SOCKET s, const char *cmd, const char *url) { int error, len; char *msg = NULL; @@ -91,7 +94,7 @@ cleanup: */ static int do_connect(transport_git *t, const char *url) { - int s = -1; + GIT_SOCKET s; char *host, *port; const char prefix[] = "git://"; int error, connected = 0; @@ -502,15 +505,18 @@ static int git_download_pack(char **out, git_transport *transport, git_repositor static int git_close(git_transport *transport) { transport_git *t = (transport_git*) transport; - int s = t->socket; int error; /* Can't do anything if there's an error, so don't bother checking */ - git_pkt_send_flush(s); - error = close(s); + git_pkt_send_flush(t->socket); + error = gitno_close(t->socket); if (error < 0) error = git__throw(GIT_EOSERR, "Failed to close socket"); +#ifdef GIT_WIN32 + WSACleanup(); +#endif + return error; } @@ -534,6 +540,9 @@ static void git_free(git_transport *transport) int git_transport_git(git_transport **out) { transport_git *t; +#ifdef GIT_WIN32 + int ret; +#endif t = git__malloc(sizeof(transport_git)); if (t == NULL) @@ -554,5 +563,13 @@ int git_transport_git(git_transport **out) *out = (git_transport *) t; +#ifdef GIT_WIN32 + ret = WSAStartup(MAKEWORD(2,2), &t->wsd); + if (ret != 0) { + git_free(*out); + return git__throw(GIT_EOSERR, "Winsock init failed"); + } +#endif + return GIT_SUCCESS; } diff --git a/src/transport_local.c b/src/transport_local.c index 4975af9ad..7e932f846 100644 --- a/src/transport_local.c +++ b/src/transport_local.c @@ -201,16 +201,19 @@ static void local_free(git_transport *transport) unsigned int i; transport_local *t = (transport_local *) transport; git_vector *vec = t->refs; + git_remote_head *h; assert(transport); - for (i = 0; i < vec->length; ++i) { - git_remote_head *h = git_vector_get(vec, i); - free(h->name); - free(h); + if (t->refs != NULL) { + git_vector_foreach (vec, i, h) { + free(h->name); + free(h); + } + git_vector_free(vec); + free(vec); } - git_vector_free(vec); - free(vec); + git_repository_free(t->repo); free(t->parent.url); free(t); @@ -228,6 +231,8 @@ int git_transport_local(git_transport **out) if (t == NULL) return GIT_ENOMEM; + memset(t, 0x0, sizeof(transport_local)); + t->parent.connect = local_connect; t->parent.ls = local_ls; t->parent.send_wants = local_send_wants;