I wrote: > I've added such tests for 'accept' and 'accept4'. More such tests are to come > for: > > bind > close > connect > dprintf > dup > dup2 > faccessat > fchdir > fchmod > fchown > fclose > fcntl > fdatasync > fdopen > fdopendir > fdutimensat > fflush > fgetc > fputc > freopen > fseeko > fstat > fsync > ftello > ftruncate > futimens > getpeername > getsockname > getsockopt > grantpt > ioctl > isatty > linkat > listen > lseek > mkfifoat > openat > posix_spawn_file_actions_addclose > posix_spawn_file_actions_adddup2 > posix_spawn_file_actions_addopen > pread > pwrite > read > readlinkat > recv > recvfrom > renameat > select > send > sendto > setsockopt > shutdown > symlinkat > ttyname_r > unlockpt > utimens > utimensat > vdprintf > write
I've added these tests now. On mingw, I got test failures for the socket functions: test-accept.c:42: assertion failed FAIL: test-accept.exe test-bind.c:46: assertion failed FAIL: test-bind.exe test-connect.c:47: assertion failed FAIL: test-connect.exe test-getpeername.c:42: assertion failed FAIL: test-getpeername.exe test-getsockname.c:42: assertion failed FAIL: test-getsockname.exe test-getsockopt.c:42: assertion failed FAIL: test-getsockopt.exe test-listen.c:38: assertion failed FAIL: test-listen.exe test-recv.c:39: assertion failed FAIL: test-recv.exe test-recvfrom.c:46: assertion failed FAIL: test-recvfrom.exe test-send.c:39: assertion failed FAIL: test-send.exe test-sendto.c:51: assertion failed FAIL: test-sendto.exe test-setsockopt.c:41: assertion failed FAIL: test-setsockopt.exe test-shutdown.c:38: assertion failed FAIL: test-shutdown.exe This fixes it. 2011-09-20 Bruno Haible <br...@clisp.org> Ensure EBADF returns for socket functions on mingw. * lib/accept.c (rpl_accept): Fail with error EBADF if the file descriptor is invalid. * lib/bind.c (rpl_bind): Likewise. * lib/connect.c (rpl_connect): Likewise. * lib/getpeername.c (rpl_getpeername): Likewise. * lib/getsockname.c (rpl_getsockname): Likewise. * lib/getsockopt.c (rpl_getsockopt): Likewise. * lib/listen.c (rpl_listen): Likewise. * lib/recv.c (rpl_recv): Likewise. * lib/recvfrom.c (rpl_recvfrom): Likewise. * lib/send.c (rpl_send): Likewise. * lib/sendto.c (rpl_sendto): Likewise. * lib/setsockopt.c (rpl_setsockopt): Likewise. * lib/shutdown.c (rpl_shutdown): Likewise. diff --git a/lib/accept.c b/lib/accept.c *** a/lib/accept.c --- b/lib/accept.c *************** *** 31,42 **** int rpl_accept (int fd, struct sockaddr *addr, socklen_t *addrlen) { ! SOCKET fh = accept (FD_TO_SOCKET (fd), addr, addrlen); ! if (fh == INVALID_SOCKET) { ! set_winsock_errno (); return -1; } else ! return SOCKET_TO_FD (fh); } --- 31,52 ---- int rpl_accept (int fd, struct sockaddr *addr, socklen_t *addrlen) { ! SOCKET sock = FD_TO_SOCKET (fd); ! ! if (sock == INVALID_SOCKET) { ! errno = EBADF; return -1; } else ! { ! SOCKET fh = accept (sock, addr, addrlen); ! if (fh == INVALID_SOCKET) ! { ! set_winsock_errno (); ! return -1; ! } ! else ! return SOCKET_TO_FD (fh); ! } } diff --git a/lib/bind.c b/lib/bind.c *** a/lib/bind.c --- b/lib/bind.c *************** *** 32,40 **** rpl_bind (int fd, const struct sockaddr *sockaddr, socklen_t len) { SOCKET sock = FD_TO_SOCKET (fd); - int r = bind (sock, sockaddr, len); - if (r < 0) - set_winsock_errno (); ! return r; } --- 32,49 ---- rpl_bind (int fd, const struct sockaddr *sockaddr, socklen_t len) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int r = bind (sock, sockaddr, len); ! if (r < 0) ! set_winsock_errno (); ! ! return r; ! } } diff --git a/lib/connect.c b/lib/connect.c *** a/lib/connect.c --- b/lib/connect.c *************** *** 32,47 **** rpl_connect (int fd, const struct sockaddr *sockaddr, socklen_t len) { SOCKET sock = FD_TO_SOCKET (fd); - int r = connect (sock, sockaddr, len); - if (r < 0) - { - /* EINPROGRESS is not returned by WinSock 2.0; for backwards - compatibility, connect(2) uses EWOULDBLOCK. */ - if (WSAGetLastError () == WSAEWOULDBLOCK) - WSASetLastError (WSAEINPROGRESS); ! set_winsock_errno (); } - - return r; } --- 32,56 ---- rpl_connect (int fd, const struct sockaddr *sockaddr, socklen_t len) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int r = connect (sock, sockaddr, len); ! if (r < 0) ! { ! /* EINPROGRESS is not returned by WinSock 2.0; for backwards ! compatibility, connect(2) uses EWOULDBLOCK. */ ! if (WSAGetLastError () == WSAEWOULDBLOCK) ! WSASetLastError (WSAEINPROGRESS); ! ! set_winsock_errno (); ! } ! ! return r; } } diff --git a/lib/getpeername.c b/lib/getpeername.c *** a/lib/getpeername.c --- b/lib/getpeername.c *************** *** 32,40 **** rpl_getpeername (int fd, struct sockaddr *addr, socklen_t *addrlen) { SOCKET sock = FD_TO_SOCKET (fd); - int r = getpeername (sock, addr, addrlen); - if (r < 0) - set_winsock_errno (); ! return r; } --- 32,49 ---- rpl_getpeername (int fd, struct sockaddr *addr, socklen_t *addrlen) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int r = getpeername (sock, addr, addrlen); ! if (r < 0) ! set_winsock_errno (); ! ! return r; ! } } diff --git a/lib/getsockname.c b/lib/getsockname.c *** a/lib/getsockname.c --- b/lib/getsockname.c *************** *** 32,40 **** rpl_getsockname (int fd, struct sockaddr *addr, socklen_t *addrlen) { SOCKET sock = FD_TO_SOCKET (fd); - int r = getsockname (sock, addr, addrlen); - if (r < 0) - set_winsock_errno (); ! return r; } --- 32,49 ---- rpl_getsockname (int fd, struct sockaddr *addr, socklen_t *addrlen) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int r = getsockname (sock, addr, addrlen); ! if (r < 0) ! set_winsock_errno (); ! ! return r; ! } } diff --git a/lib/getsockopt.c b/lib/getsockopt.c *** a/lib/getsockopt.c --- b/lib/getsockopt.c *************** *** 37,68 **** int rpl_getsockopt (int fd, int level, int optname, void *optval, socklen_t *optlen) { - int r; SOCKET sock = FD_TO_SOCKET (fd); ! if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { ! int milliseconds; ! int milliseconds_len = sizeof (int); ! struct timeval tv; ! size_t n; ! r = getsockopt (sock, level, optname, (char *) &milliseconds, ! &milliseconds_len); ! tv.tv_sec = milliseconds / 1000; ! tv.tv_usec = (milliseconds - 1000 * tv.tv_sec) * 1000; ! n = sizeof (struct timeval); ! if (n > *optlen) ! n = *optlen; ! memcpy (optval, &tv, n); ! *optlen = n; } else { ! r = getsockopt (sock, level, optname, optval, optlen); ! } ! if (r < 0) ! set_winsock_errno (); ! return r; } --- 37,79 ---- int rpl_getsockopt (int fd, int level, int optname, void *optval, socklen_t *optlen) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) { ! errno = EBADF; ! return -1; } else { ! int r; ! ! if (level == SOL_SOCKET ! && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) ! { ! int milliseconds; ! int milliseconds_len = sizeof (int); ! struct timeval tv; ! size_t n; ! r = getsockopt (sock, level, optname, (char *) &milliseconds, ! &milliseconds_len); ! tv.tv_sec = milliseconds / 1000; ! tv.tv_usec = (milliseconds - 1000 * tv.tv_sec) * 1000; ! n = sizeof (struct timeval); ! if (n > *optlen) ! n = *optlen; ! memcpy (optval, &tv, n); ! *optlen = n; ! } ! else ! { ! r = getsockopt (sock, level, optname, optval, optlen); ! } ! if (r < 0) ! set_winsock_errno (); ! ! return r; ! } } diff --git a/lib/listen.c b/lib/listen.c *** a/lib/listen.c --- b/lib/listen.c *************** *** 32,40 **** rpl_listen (int fd, int backlog) { SOCKET sock = FD_TO_SOCKET (fd); - int r = listen (sock, backlog); - if (r < 0) - set_winsock_errno (); ! return r; } --- 32,49 ---- rpl_listen (int fd, int backlog) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int r = listen (sock, backlog); ! if (r < 0) ! set_winsock_errno (); ! ! return r; ! } } diff --git a/lib/recv.c b/lib/recv.c *** a/lib/recv.c --- b/lib/recv.c *************** *** 32,40 **** rpl_recv (int fd, void *buf, size_t len, int flags) { SOCKET sock = FD_TO_SOCKET (fd); - int r = recv (sock, buf, len, flags); - if (r < 0) - set_winsock_errno (); ! return r; } --- 32,49 ---- rpl_recv (int fd, void *buf, size_t len, int flags) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int r = recv (sock, buf, len, flags); ! if (r < 0) ! set_winsock_errno (); ! ! return r; ! } } diff --git a/lib/recvfrom.c b/lib/recvfrom.c *** a/lib/recvfrom.c --- b/lib/recvfrom.c *************** *** 32,48 **** rpl_recvfrom (int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { - int frombufsize = (from != NULL ? *fromlen : 0); SOCKET sock = FD_TO_SOCKET (fd); - int r = recvfrom (sock, buf, len, flags, from, fromlen); ! if (r < 0) ! set_winsock_errno (); ! ! /* Winsock recvfrom() only returns a valid 'from' when the socket is ! connectionless. POSIX gives a valid 'from' for all types of sockets. */ ! else if (from != NULL && *fromlen == frombufsize) ! rpl_getpeername (fd, from, fromlen); ! ! return r; } --- 32,58 ---- rpl_recvfrom (int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int frombufsize = (from != NULL ? *fromlen : 0); ! int r = recvfrom (sock, buf, len, flags, from, fromlen); ! ! if (r < 0) ! set_winsock_errno (); ! ! /* Winsock recvfrom() only returns a valid 'from' when the socket is ! connectionless. POSIX gives a valid 'from' for all types of ! sockets. */ ! else if (from != NULL && *fromlen == frombufsize) ! rpl_getpeername (fd, from, fromlen); ! ! return r; ! } } diff --git a/lib/send.c b/lib/send.c *** a/lib/send.c --- b/lib/send.c *************** *** 32,40 **** rpl_send (int fd, const void *buf, size_t len, int flags) { SOCKET sock = FD_TO_SOCKET (fd); - int r = send (sock, buf, len, flags); - if (r < 0) - set_winsock_errno (); ! return r; } --- 32,49 ---- rpl_send (int fd, const void *buf, size_t len, int flags) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int r = send (sock, buf, len, flags); ! if (r < 0) ! set_winsock_errno (); ! ! return r; ! } } diff --git a/lib/sendto.c b/lib/sendto.c *** a/lib/sendto.c --- b/lib/sendto.c *************** *** 33,41 **** const struct sockaddr *to, socklen_t tolen) { SOCKET sock = FD_TO_SOCKET (fd); - int r = sendto (sock, buf, len, flags, to, tolen); - if (r < 0) - set_winsock_errno (); ! return r; } --- 33,50 ---- const struct sockaddr *to, socklen_t tolen) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int r = sendto (sock, buf, len, flags, to, tolen); ! if (r < 0) ! set_winsock_errno (); ! ! return r; ! } } diff --git a/lib/setsockopt.c b/lib/setsockopt.c *** a/lib/setsockopt.c --- b/lib/setsockopt.c *************** *** 34,56 **** int rpl_setsockopt (int fd, int level, int optname, const void *optval, socklen_t optlen) { - int r; SOCKET sock = FD_TO_SOCKET (fd); ! if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { ! const struct timeval *tv = optval; ! int milliseconds = tv->tv_sec * 1000 + tv->tv_usec / 1000; ! optval = &milliseconds; ! r = setsockopt (sock, level, optname, optval, sizeof (int)); } else { ! r = setsockopt (sock, level, optname, optval, optlen); ! } ! if (r < 0) ! set_winsock_errno (); ! return r; } --- 34,65 ---- int rpl_setsockopt (int fd, int level, int optname, const void *optval, socklen_t optlen) { SOCKET sock = FD_TO_SOCKET (fd); + int r; ! if (sock == INVALID_SOCKET) { ! errno = EBADF; ! return -1; } else { ! if (level == SOL_SOCKET ! && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) ! { ! const struct timeval *tv = optval; ! int milliseconds = tv->tv_sec * 1000 + tv->tv_usec / 1000; ! optval = &milliseconds; ! r = setsockopt (sock, level, optname, optval, sizeof (int)); ! } ! else ! { ! r = setsockopt (sock, level, optname, optval, optlen); ! } ! if (r < 0) ! set_winsock_errno (); ! return r; ! } } diff --git a/lib/shutdown.c b/lib/shutdown.c *** a/lib/shutdown.c --- b/lib/shutdown.c *************** *** 32,40 **** rpl_shutdown (int fd, int how) { SOCKET sock = FD_TO_SOCKET (fd); - int r = shutdown (sock, how); - if (r < 0) - set_winsock_errno (); ! return r; } --- 32,49 ---- rpl_shutdown (int fd, int how) { SOCKET sock = FD_TO_SOCKET (fd); ! if (sock == INVALID_SOCKET) ! { ! errno = EBADF; ! return -1; ! } ! else ! { ! int r = shutdown (sock, how); ! if (r < 0) ! set_winsock_errno (); ! ! return r; ! } } -- In memoriam Pierre Goldman <http://en.wikipedia.org/wiki/Pierre_Goldman>