From f48ce084de9afc7e0c5225b3fa51f4374b42f2ee Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 2 Feb 2007 15:41:43 +0100 Subject: [PATCH] MinGW: Make git native protocol work. As it turns out, the things returned by Winsock2's socket() are handles that can be passed to ReadFile()/WriteFile() - almost. The way this works is by wrapping those handles into file descriptors with _open_osfhandle(). But it turns out that the sockets created by the plain socket() function are prepared for "overlapped" I/O, which confuses ReadFile()/WriteFile(). Therefore, a reimplementation is provided that uses WSASocket() to explicitly asks for non-overlapped sockets. Special thanks got to H. Peter Anvin, who provided the necessary clues. --- README.MinGW | 6 +++--- compat/mingw.c | 19 +++++++++++++++++++ connect.c | 16 ++++++++++++++++ git-compat-util.h | 3 +++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/README.MinGW b/README.MinGW index 3c67064f3f..4a454edf2c 100644 --- a/README.MinGW +++ b/README.MinGW @@ -50,14 +50,14 @@ This works: - All the plumbings. - Many porcelains, in particular, checkout, add, rm, commit, diff, branch, merge, rebase, log, show, bisect, grep... -- pull, clone, fetch, push via ssh. +- pull, clone, fetch, push via native git protocal as well as ssh. - Local pull, clone, fetch, push. - gitk, if invoked as "wish84 \bin\gitk", but there are - artefacts in its layout. + artefacts in its layout. A workaround by Mark Levedahl is in + branch 'devel'. This does not work: -- pull, clone, fetch, push via native GIT protocol. - daemon, svn, *import, cvs* - and certainly a lot more that I never have found a need to look at. diff --git a/compat/mingw.c b/compat/mingw.c index 7f5067676c..6887968a10 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -293,3 +293,22 @@ void mingw_execve(const char *cmd, const char **argv, const char **env) exit(ret); } } + +int mingw_socket(int domain, int type, int protocol) +{ + SOCKET s = WSASocket(domain, type, protocol, NULL, 0, 0); + if (s == INVALID_SOCKET) { + /* + * WSAGetLastError() values are regular BSD error codes + * biased by WSABASEERR. + * However, strerror() does not know about networking + * specific errors, which are values beginning at 38 or so. + * Therefore, we choose to leave the biased error code + * in errno so that _if_ someone looks up the code somewhere, + * then it is at least the number that are usually listed. + */ + errno = WSAGetLastError(); + return -1; + } + return s; +} diff --git a/connect.c b/connect.c index 3612c5538c..39cc73e9aa 100644 --- a/connect.c +++ b/connect.c @@ -527,7 +527,23 @@ static int git_tcp_connect_sock(char *host) static void git_tcp_connect(int fd[2], char *host) { +#ifndef __MINGW32__ int sockfd = git_tcp_connect_sock(host); +#else + int sockfd; + WSADATA wsa; + + if (WSAStartup(MAKEWORD(2,2), &wsa)) + die("unable to initialize winsock subsystem, error %d", + WSAGetLastError()); + atexit((void(*)(void)) WSACleanup); + + sockfd = git_tcp_connect_sock(host); + /* convert into a file descriptor */ + if ((sockfd = _open_osfhandle(sockfd, O_RDWR|O_BINARY)) < 0) + die("unable to make a socket file descriptor: %s", + strerror(errno)); +#endif fd[0] = sockfd; fd[1] = dup(sockfd); diff --git a/git-compat-util.h b/git-compat-util.h index 37ac8dbc23..cafca04d01 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -374,6 +374,9 @@ struct tm *localtime_r(const time_t *timep, struct tm *result); char *mingw_getcwd(char *pointer, int len); #define getcwd mingw_getcwd +int mingw_socket(int domain, int type, int protocol); +#define socket mingw_socket + #define setlinebuf(x) #define fsync(x)