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 <johannes.sixt@telecom.at>
This commit is contained in:
Johannes Sixt
2007-09-20 14:58:00 +02:00
parent 0cce83445c
commit b49fa05b92

View File

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