Fix fcntl() emulation for Windows

F_GETFL always failed with WSAEINVAL.  io_noblocking() always failed
without doing anything.  Callers didn't check for failure, and newly
opened sockets remained blocking.  But because because
WSAEventSelect() makes sockets non-blocking automatically, they became
non-blocking soon enough to keep things working.

Remove the broken code to query the non-blocking state, and just
return 0.  Document why this works.

While there, simplify the F_SETFL case by using ioctlsocket() instead
of WSAIoctl().
This commit is contained in:
Markus Armbruster 2009-06-14 18:30:53 +02:00
parent 1d1e789782
commit 205206b3df

View file

@ -642,18 +642,17 @@ fileno(FILE *stream)
/* /*
* POSIX equivalent for fcntl(). * POSIX equivalent for fcntl().
* Currently supports only the F_GETFL/F_SETFL/O_NONBLOCK * Horrible hacks, just good enough support Empire's use of fcntl().
* Currently ignores F_GETLK/F_SETLK as the file locks are * F_GETFL / F_SETFL support making a socket (non-)blocking by getting
* implement in open() * flags, adding or removing O_NONBLOCK, and setting the result.
* F_SETLK does nothing. Instead, we lock in posix_open().
*/ */
int int
fcntl(int fd, int cmd, ...) fcntl(int fd, int cmd, ...)
{ {
va_list ap; va_list ap;
int value; int value;
unsigned int nonblocking; unsigned long nonblocking;
int result;
long bytes_returned;
int handle; int handle;
enum fdmap_io_type type; enum fdmap_io_type type;
@ -663,52 +662,24 @@ fcntl(int fd, int cmd, ...)
switch (cmd) switch (cmd)
{ {
case F_GETFL: case F_GETFL:
/* if (type == FDMAP_IO_SOCKET)
* F_GETFL and F_SETFL only support O_NONBLOCK return 0;
* for sockets currently
*/
if (type == FDMAP_IO_SOCKET) {
result = WSAIoctl(handle, FIONBIO, NULL, 0,&nonblocking,
sizeof (nonblocking), &bytes_returned, NULL, NULL);
if(result < 0) {
errno = WSAGetLastError();
return -1;
}
if (nonblocking)
return O_NONBLOCK;
else
return 0;
}
break; break;
case F_SETFL: case F_SETFL:
if (type == FDMAP_IO_SOCKET) { if (type == FDMAP_IO_SOCKET) {
va_start(ap, cmd); va_start(ap, cmd);
value = va_arg(ap, int); value = va_arg(ap, int);
va_end(ap); va_end(ap);
if (value & O_NONBLOCK) nonblocking = (value & O_NONBLOCK) != 0;
nonblocking = 1;
else
nonblocking = 0;
result = WSAIoctl(handle, FIONBIO, &nonblocking, if (ioctlsocket(handle, FIONBIO, &nonblocking) == SOCKET_ERROR) {
sizeof (nonblocking), NULL, 0, &bytes_returned,
NULL, NULL);
if(result < 0) {
errno = WSAGetLastError(); errno = WSAGetLastError();
return -1; return -1;
} }
return result; return 0;
} }
break; break;
case F_SETLK: case F_SETLK:
/*
* The POSIX equivalent is not available in WIN32
* That implement the file locking in the file open
* by using sopen instead of open.
*/
return 0; return 0;
} }
errno = EINVAL; errno = EINVAL;