From b49fa05b92a7a369beca1de67fded5a6da500f9c Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Thu, 20 Sep 2007 14:58:00 +0200 Subject: [PATCH] Handle fstat() of a socket descriptor. GetFileInformationByHandle() fails if it is passed a WinSock handle. Fortunately, the failure can be distinguished by the error code, and we can in this case pretend that the fstat() was actually successful. This is a valid thing to do: Calling fstat() on a descriptor makes only sense if either the caller needs information on the file (in which case we would not reach this error condition), or if it wants to distinguish a socket from a file (which implies that the caller will have to test st_mode, which happens to be the only field that we can fill in). Signed-off-by: Johannes Sixt --- compat/mingw.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/compat/mingw.c b/compat/mingw.c index 20eadd2334..166e2ad5f0 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -123,8 +123,14 @@ int git_fstat(int fd, struct stat *buf) { HANDLE fh = (HANDLE)_get_osfhandle(fd); BY_HANDLE_FILE_INFORMATION fdata; + char dummy[sizeof(void*)]; + int s = sizeof(void*); - if (fh != INVALID_HANDLE_VALUE && GetFileInformationByHandle(fh, &fdata)) { + if (fh == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + if (GetFileInformationByHandle(fh, &fdata)) { int fMode = S_IREAD; if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) fMode |= S_IFDIR; @@ -145,7 +151,22 @@ int git_fstat(int fd, struct stat *buf) buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); return 0; } - errno = EBADF; + switch (GetLastError()) { + case ERROR_INVALID_FUNCTION: + /* check for socket */ + if (getsockopt((int)fh, SOL_SOCKET, SO_KEEPALIVE, dummy, &s) && + WSAGetLastError() == WSAENOTSOCK) + goto badf; + memset(buf, sizeof(*buf), 0); + buf->st_mode = S_IREAD|S_IWRITE; + buf->st_mode |= 0x140000; /* S_IFSOCK */ + return 0; + default: + case ERROR_INVALID_HANDLE: + badf: + errno = EBADF; + break; + } return -1; }