@@ -2021,26 +2021,158 @@ static void ensure_socket_initialization(void)
20212021 initialized = 1 ;
20222022}
20232023
2024+ static int winsock_error_to_errno (DWORD err )
2025+ {
2026+ switch (err ) {
2027+ case WSAEINTR : return EINTR ;
2028+ case WSAEBADF : return EBADF ;
2029+ case WSAEACCES : return EACCES ;
2030+ case WSAEFAULT : return EFAULT ;
2031+ case WSAEINVAL : return EINVAL ;
2032+ case WSAEMFILE : return EMFILE ;
2033+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2034+ case WSAEINPROGRESS : return EINPROGRESS ;
2035+ case WSAEALREADY : return EALREADY ;
2036+ case WSAENOTSOCK : return ENOTSOCK ;
2037+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2038+ case WSAEMSGSIZE : return EMSGSIZE ;
2039+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2040+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2041+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2042+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2043+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2044+ case WSAEADDRINUSE : return EADDRINUSE ;
2045+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2046+ case WSAENETDOWN : return ENETDOWN ;
2047+ case WSAENETUNREACH : return ENETUNREACH ;
2048+ case WSAENETRESET : return ENETRESET ;
2049+ case WSAECONNABORTED : return ECONNABORTED ;
2050+ case WSAECONNRESET : return ECONNRESET ;
2051+ case WSAENOBUFS : return ENOBUFS ;
2052+ case WSAEISCONN : return EISCONN ;
2053+ case WSAENOTCONN : return ENOTCONN ;
2054+ case WSAETIMEDOUT : return ETIMEDOUT ;
2055+ case WSAECONNREFUSED : return ECONNREFUSED ;
2056+ case WSAELOOP : return ELOOP ;
2057+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2058+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2059+ case WSAENOTEMPTY : return ENOTEMPTY ;
2060+ /* No errno equivalent; default to EIO */
2061+ case WSAESOCKTNOSUPPORT :
2062+ case WSAEPFNOSUPPORT :
2063+ case WSAESHUTDOWN :
2064+ case WSAETOOMANYREFS :
2065+ case WSAEHOSTDOWN :
2066+ case WSAEPROCLIM :
2067+ case WSAEUSERS :
2068+ case WSAEDQUOT :
2069+ case WSAESTALE :
2070+ case WSAEREMOTE :
2071+ case WSASYSNOTREADY :
2072+ case WSAVERNOTSUPPORTED :
2073+ case WSANOTINITIALISED :
2074+ case WSAEDISCON :
2075+ case WSAENOMORE :
2076+ case WSAECANCELLED :
2077+ case WSAEINVALIDPROCTABLE :
2078+ case WSAEINVALIDPROVIDER :
2079+ case WSAEPROVIDERFAILEDINIT :
2080+ case WSASYSCALLFAILURE :
2081+ case WSASERVICE_NOT_FOUND :
2082+ case WSATYPE_NOT_FOUND :
2083+ case WSA_E_NO_MORE :
2084+ case WSA_E_CANCELLED :
2085+ case WSAEREFUSED :
2086+ case WSAHOST_NOT_FOUND :
2087+ case WSATRY_AGAIN :
2088+ case WSANO_RECOVERY :
2089+ case WSANO_DATA :
2090+ case WSA_QOS_RECEIVERS :
2091+ case WSA_QOS_SENDERS :
2092+ case WSA_QOS_NO_SENDERS :
2093+ case WSA_QOS_NO_RECEIVERS :
2094+ case WSA_QOS_REQUEST_CONFIRMED :
2095+ case WSA_QOS_ADMISSION_FAILURE :
2096+ case WSA_QOS_POLICY_FAILURE :
2097+ case WSA_QOS_BAD_STYLE :
2098+ case WSA_QOS_BAD_OBJECT :
2099+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2100+ case WSA_QOS_GENERIC_ERROR :
2101+ case WSA_QOS_ESERVICETYPE :
2102+ case WSA_QOS_EFLOWSPEC :
2103+ case WSA_QOS_EPROVSPECBUF :
2104+ case WSA_QOS_EFILTERSTYLE :
2105+ case WSA_QOS_EFILTERTYPE :
2106+ case WSA_QOS_EFILTERCOUNT :
2107+ case WSA_QOS_EOBJLENGTH :
2108+ case WSA_QOS_EFLOWCOUNT :
2109+ #ifndef _MSC_VER
2110+ case WSA_QOS_EUNKNOWNPSOBJ :
2111+ #endif
2112+ case WSA_QOS_EPOLICYOBJ :
2113+ case WSA_QOS_EFLOWDESC :
2114+ case WSA_QOS_EPSFLOWSPEC :
2115+ case WSA_QOS_EPSFILTERSPEC :
2116+ case WSA_QOS_ESDMODEOBJ :
2117+ case WSA_QOS_ESHAPERATEOBJ :
2118+ case WSA_QOS_RESERVED_PETYPE :
2119+ default : return EIO ;
2120+ }
2121+ }
2122+
2123+ /*
2124+ * On Windows, `errno` is a global macro to a function call.
2125+ * This makes it difficult to debug and single-step our mappings.
2126+ */
2127+ static inline void set_wsa_errno (void )
2128+ {
2129+ DWORD wsa = WSAGetLastError ();
2130+ int e = winsock_error_to_errno (wsa );
2131+ errno = e ;
2132+
2133+ #ifdef DEBUG_WSA_ERRNO
2134+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2135+ fflush (stderr );
2136+ #endif
2137+ }
2138+
2139+ static inline int winsock_return (int ret )
2140+ {
2141+ if (ret < 0 )
2142+ set_wsa_errno ();
2143+
2144+ return ret ;
2145+ }
2146+
2147+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2148+
20242149#undef gethostname
20252150int mingw_gethostname (char * name , int namelen )
20262151{
2027- ensure_socket_initialization ();
2028- return gethostname (name , namelen );
2152+ ensure_socket_initialization ();
2153+ WINSOCK_RETURN ( gethostname (name , namelen ) );
20292154}
20302155
20312156#undef gethostbyname
20322157struct hostent * mingw_gethostbyname (const char * host )
20332158{
2159+ struct hostent * ret ;
2160+
20342161 ensure_socket_initialization ();
2035- return gethostbyname (host );
2162+
2163+ ret = gethostbyname (host );
2164+ if (!ret )
2165+ set_wsa_errno ();
2166+
2167+ return ret ;
20362168}
20372169
20382170#undef getaddrinfo
20392171int mingw_getaddrinfo (const char * node , const char * service ,
20402172 const struct addrinfo * hints , struct addrinfo * * res )
20412173{
20422174 ensure_socket_initialization ();
2043- return getaddrinfo (node , service , hints , res );
2175+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
20442176}
20452177
20462178int mingw_socket (int domain , int type , int protocol )
@@ -2060,7 +2192,7 @@ int mingw_socket(int domain, int type, int protocol)
20602192 * in errno so that _if_ someone looks up the code somewhere,
20612193 * then it is at least the number that are usually listed.
20622194 */
2063- errno = WSAGetLastError ();
2195+ set_wsa_errno ();
20642196 return -1 ;
20652197 }
20662198 /* convert into a file descriptor */
@@ -2076,35 +2208,35 @@ int mingw_socket(int domain, int type, int protocol)
20762208int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
20772209{
20782210 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2079- return connect (s , sa , sz );
2211+ WINSOCK_RETURN ( connect (s , sa , sz ) );
20802212}
20812213
20822214#undef bind
20832215int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
20842216{
20852217 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2086- return bind (s , sa , sz );
2218+ WINSOCK_RETURN ( bind (s , sa , sz ) );
20872219}
20882220
20892221#undef setsockopt
20902222int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
20912223{
20922224 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2093- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2225+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
20942226}
20952227
20962228#undef shutdown
20972229int mingw_shutdown (int sockfd , int how )
20982230{
20992231 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2100- return shutdown (s , how );
2232+ WINSOCK_RETURN ( shutdown (s , how ) );
21012233}
21022234
21032235#undef listen
21042236int mingw_listen (int sockfd , int backlog )
21052237{
21062238 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2107- return listen (s , backlog );
2239+ WINSOCK_RETURN ( listen (s , backlog ) );
21082240}
21092241
21102242#undef accept
@@ -2115,6 +2247,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
21152247 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
21162248 SOCKET s2 = accept (s1 , sa , sz );
21172249
2250+ if (s2 == INVALID_SOCKET ) {
2251+ set_wsa_errno ();
2252+ return -1 ;
2253+ }
2254+
21182255 /* convert into a file descriptor */
21192256 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
21202257 int err = errno ;
0 commit comments