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.
This commit is contained in:
Johannes Sixt
2007-02-02 15:41:43 +01:00
parent fef988b62b
commit f48ce084de
4 changed files with 41 additions and 3 deletions

View File

@@ -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 <prefix>\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.

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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)