changeset 15727:144db791c6fa

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.
author Bruno Haible <bruno@clisp.org>
date Wed, 21 Sep 2011 00:20:59 +0200
parents 1a3894d5ce47
children d653c053dc60
files ChangeLog lib/accept.c lib/bind.c lib/connect.c lib/getpeername.c lib/getsockname.c lib/getsockopt.c lib/listen.c lib/recv.c lib/recvfrom.c lib/send.c lib/sendto.c lib/setsockopt.c lib/shutdown.c
diffstat 14 files changed, 224 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2011-09-20  Bruno Haible  <bruno@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.
+
 2011-09-20  Bruno Haible  <bruno@clisp.org>
 
 	select tests: EBADF tests.
--- a/lib/accept.c
+++ b/lib/accept.c
@@ -31,12 +31,22 @@
 int
 rpl_accept (int fd, struct sockaddr *addr, socklen_t *addrlen)
 {
-  SOCKET fh = accept (FD_TO_SOCKET (fd), addr, addrlen);
-  if (fh == INVALID_SOCKET)
+  SOCKET sock = FD_TO_SOCKET (fd);
+
+  if (sock == INVALID_SOCKET)
     {
-      set_winsock_errno ();
+      errno = EBADF;
       return -1;
     }
   else
-    return SOCKET_TO_FD (fh);
+    {
+      SOCKET fh = accept (sock, addr, addrlen);
+      if (fh == INVALID_SOCKET)
+        {
+          set_winsock_errno ();
+          return -1;
+        }
+      else
+        return SOCKET_TO_FD (fh);
+    }
 }
--- a/lib/bind.c
+++ b/lib/bind.c
@@ -32,9 +32,18 @@
 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;
+  if (sock == INVALID_SOCKET)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  else
+    {
+      int r = bind (sock, sockaddr, len);
+      if (r < 0)
+        set_winsock_errno ();
+
+      return r;
+    }
 }
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -32,16 +32,25 @@
 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)
+
+  if (sock == INVALID_SOCKET)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  else
     {
-      /* EINPROGRESS is not returned by WinSock 2.0; for backwards
-         compatibility, connect(2) uses EWOULDBLOCK.  */
-      if (WSAGetLastError () == WSAEWOULDBLOCK)
-        WSASetLastError (WSAEINPROGRESS);
+      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 ();
-    }
+          set_winsock_errno ();
+        }
 
-  return r;
+      return r;
+    }
 }
--- a/lib/getpeername.c
+++ b/lib/getpeername.c
@@ -32,9 +32,18 @@
 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;
+  if (sock == INVALID_SOCKET)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  else
+    {
+      int r = getpeername (sock, addr, addrlen);
+      if (r < 0)
+        set_winsock_errno ();
+
+      return r;
+    }
 }
--- a/lib/getsockname.c
+++ b/lib/getsockname.c
@@ -32,9 +32,18 @@
 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;
+  if (sock == INVALID_SOCKET)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  else
+    {
+      int r = getsockname (sock, addr, addrlen);
+      if (r < 0)
+        set_winsock_errno ();
+
+      return r;
+    }
 }
--- a/lib/getsockopt.c
+++ b/lib/getsockopt.c
@@ -37,32 +37,43 @@
 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))
+  if (sock == INVALID_SOCKET)
     {
-      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;
+      errno = EBADF;
+      return -1;
     }
   else
     {
-      r = getsockopt (sock, level, optname, optval, optlen);
-    }
+      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;
 
-  if (r < 0)
-    set_winsock_errno ();
+          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);
+        }
 
-  return r;
+      if (r < 0)
+        set_winsock_errno ();
+
+      return r;
+    }
 }
--- a/lib/listen.c
+++ b/lib/listen.c
@@ -32,9 +32,18 @@
 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;
+  if (sock == INVALID_SOCKET)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  else
+    {
+      int r = listen (sock, backlog);
+      if (r < 0)
+        set_winsock_errno ();
+
+      return r;
+    }
 }
--- a/lib/recv.c
+++ b/lib/recv.c
@@ -32,9 +32,18 @@
 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;
+  if (sock == INVALID_SOCKET)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  else
+    {
+      int r = recv (sock, buf, len, flags);
+      if (r < 0)
+        set_winsock_errno ();
+
+      return r;
+    }
 }
--- a/lib/recvfrom.c
+++ b/lib/recvfrom.c
@@ -32,17 +32,27 @@
 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 ();
+  if (sock == INVALID_SOCKET)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  else
+    {
+      int frombufsize = (from != NULL ? *fromlen : 0);
+      int r = recvfrom (sock, buf, len, flags, from, fromlen);
 
-  /* 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);
+      if (r < 0)
+        set_winsock_errno ();
 
-  return r;
+      /* 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;
+    }
 }
--- a/lib/send.c
+++ b/lib/send.c
@@ -32,9 +32,18 @@
 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;
+  if (sock == INVALID_SOCKET)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  else
+    {
+      int r = send (sock, buf, len, flags);
+      if (r < 0)
+        set_winsock_errno ();
+
+      return r;
+    }
 }
--- a/lib/sendto.c
+++ b/lib/sendto.c
@@ -33,9 +33,18 @@
             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;
+  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;
+    }
 }
--- a/lib/setsockopt.c
+++ b/lib/setsockopt.c
@@ -34,23 +34,32 @@
 int
 rpl_setsockopt (int fd, int level, int optname, const void *optval, socklen_t optlen)
 {
+  SOCKET sock = FD_TO_SOCKET (fd);
   int r;
-  SOCKET sock = FD_TO_SOCKET (fd);
 
-  if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
+  if (sock == INVALID_SOCKET)
     {
-      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));
+      errno = EBADF;
+      return -1;
     }
   else
     {
-      r = setsockopt (sock, level, optname, optval, optlen);
-    }
+      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 ();
+      if (r < 0)
+        set_winsock_errno ();
 
-  return r;
+      return r;
+    }
 }
--- a/lib/shutdown.c
+++ b/lib/shutdown.c
@@ -32,9 +32,18 @@
 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;
+  if (sock == INVALID_SOCKET)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  else
+    {
+      int r = shutdown (sock, how);
+      if (r < 0)
+        set_winsock_errno ();
+
+      return r;
+    }
 }