@@ -2186,26 +2186,158 @@ static void ensure_socket_initialization(void)
21862186 initialized = 1 ;
21872187}
21882188
2189+ static int winsock_error_to_errno (DWORD err )
2190+ {
2191+ switch (err ) {
2192+ case WSAEINTR : return EINTR ;
2193+ case WSAEBADF : return EBADF ;
2194+ case WSAEACCES : return EACCES ;
2195+ case WSAEFAULT : return EFAULT ;
2196+ case WSAEINVAL : return EINVAL ;
2197+ case WSAEMFILE : return EMFILE ;
2198+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2199+ case WSAEINPROGRESS : return EINPROGRESS ;
2200+ case WSAEALREADY : return EALREADY ;
2201+ case WSAENOTSOCK : return ENOTSOCK ;
2202+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2203+ case WSAEMSGSIZE : return EMSGSIZE ;
2204+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2205+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2206+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2207+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2208+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2209+ case WSAEADDRINUSE : return EADDRINUSE ;
2210+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2211+ case WSAENETDOWN : return ENETDOWN ;
2212+ case WSAENETUNREACH : return ENETUNREACH ;
2213+ case WSAENETRESET : return ENETRESET ;
2214+ case WSAECONNABORTED : return ECONNABORTED ;
2215+ case WSAECONNRESET : return ECONNRESET ;
2216+ case WSAENOBUFS : return ENOBUFS ;
2217+ case WSAEISCONN : return EISCONN ;
2218+ case WSAENOTCONN : return ENOTCONN ;
2219+ case WSAETIMEDOUT : return ETIMEDOUT ;
2220+ case WSAECONNREFUSED : return ECONNREFUSED ;
2221+ case WSAELOOP : return ELOOP ;
2222+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2223+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2224+ case WSAENOTEMPTY : return ENOTEMPTY ;
2225+ /* No errno equivalent; default to EIO */
2226+ case WSAESOCKTNOSUPPORT :
2227+ case WSAEPFNOSUPPORT :
2228+ case WSAESHUTDOWN :
2229+ case WSAETOOMANYREFS :
2230+ case WSAEHOSTDOWN :
2231+ case WSAEPROCLIM :
2232+ case WSAEUSERS :
2233+ case WSAEDQUOT :
2234+ case WSAESTALE :
2235+ case WSAEREMOTE :
2236+ case WSASYSNOTREADY :
2237+ case WSAVERNOTSUPPORTED :
2238+ case WSANOTINITIALISED :
2239+ case WSAEDISCON :
2240+ case WSAENOMORE :
2241+ case WSAECANCELLED :
2242+ case WSAEINVALIDPROCTABLE :
2243+ case WSAEINVALIDPROVIDER :
2244+ case WSAEPROVIDERFAILEDINIT :
2245+ case WSASYSCALLFAILURE :
2246+ case WSASERVICE_NOT_FOUND :
2247+ case WSATYPE_NOT_FOUND :
2248+ case WSA_E_NO_MORE :
2249+ case WSA_E_CANCELLED :
2250+ case WSAEREFUSED :
2251+ case WSAHOST_NOT_FOUND :
2252+ case WSATRY_AGAIN :
2253+ case WSANO_RECOVERY :
2254+ case WSANO_DATA :
2255+ case WSA_QOS_RECEIVERS :
2256+ case WSA_QOS_SENDERS :
2257+ case WSA_QOS_NO_SENDERS :
2258+ case WSA_QOS_NO_RECEIVERS :
2259+ case WSA_QOS_REQUEST_CONFIRMED :
2260+ case WSA_QOS_ADMISSION_FAILURE :
2261+ case WSA_QOS_POLICY_FAILURE :
2262+ case WSA_QOS_BAD_STYLE :
2263+ case WSA_QOS_BAD_OBJECT :
2264+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2265+ case WSA_QOS_GENERIC_ERROR :
2266+ case WSA_QOS_ESERVICETYPE :
2267+ case WSA_QOS_EFLOWSPEC :
2268+ case WSA_QOS_EPROVSPECBUF :
2269+ case WSA_QOS_EFILTERSTYLE :
2270+ case WSA_QOS_EFILTERTYPE :
2271+ case WSA_QOS_EFILTERCOUNT :
2272+ case WSA_QOS_EOBJLENGTH :
2273+ case WSA_QOS_EFLOWCOUNT :
2274+ #ifndef _MSC_VER
2275+ case WSA_QOS_EUNKNOWNPSOBJ :
2276+ #endif
2277+ case WSA_QOS_EPOLICYOBJ :
2278+ case WSA_QOS_EFLOWDESC :
2279+ case WSA_QOS_EPSFLOWSPEC :
2280+ case WSA_QOS_EPSFILTERSPEC :
2281+ case WSA_QOS_ESDMODEOBJ :
2282+ case WSA_QOS_ESHAPERATEOBJ :
2283+ case WSA_QOS_RESERVED_PETYPE :
2284+ default : return EIO ;
2285+ }
2286+ }
2287+
2288+ /*
2289+ * On Windows, `errno` is a global macro to a function call.
2290+ * This makes it difficult to debug and single-step our mappings.
2291+ */
2292+ static inline void set_wsa_errno (void )
2293+ {
2294+ DWORD wsa = WSAGetLastError ();
2295+ int e = winsock_error_to_errno (wsa );
2296+ errno = e ;
2297+
2298+ #ifdef DEBUG_WSA_ERRNO
2299+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2300+ fflush (stderr );
2301+ #endif
2302+ }
2303+
2304+ static inline int winsock_return (int ret )
2305+ {
2306+ if (ret < 0 )
2307+ set_wsa_errno ();
2308+
2309+ return ret ;
2310+ }
2311+
2312+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2313+
21892314#undef gethostname
21902315int mingw_gethostname (char * name , int namelen )
21912316{
2192- ensure_socket_initialization ();
2193- return gethostname (name , namelen );
2317+ ensure_socket_initialization ();
2318+ WINSOCK_RETURN ( gethostname (name , namelen ) );
21942319}
21952320
21962321#undef gethostbyname
21972322struct hostent * mingw_gethostbyname (const char * host )
21982323{
2324+ struct hostent * ret ;
2325+
21992326 ensure_socket_initialization ();
2200- return gethostbyname (host );
2327+
2328+ ret = gethostbyname (host );
2329+ if (!ret )
2330+ set_wsa_errno ();
2331+
2332+ return ret ;
22012333}
22022334
22032335#undef getaddrinfo
22042336int mingw_getaddrinfo (const char * node , const char * service ,
22052337 const struct addrinfo * hints , struct addrinfo * * res )
22062338{
22072339 ensure_socket_initialization ();
2208- return getaddrinfo (node , service , hints , res );
2340+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
22092341}
22102342
22112343int mingw_socket (int domain , int type , int protocol )
@@ -2225,7 +2357,7 @@ int mingw_socket(int domain, int type, int protocol)
22252357 * in errno so that _if_ someone looks up the code somewhere,
22262358 * then it is at least the number that are usually listed.
22272359 */
2228- errno = WSAGetLastError ();
2360+ set_wsa_errno ();
22292361 return -1 ;
22302362 }
22312363 /* convert into a file descriptor */
@@ -2241,35 +2373,35 @@ int mingw_socket(int domain, int type, int protocol)
22412373int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
22422374{
22432375 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2244- return connect (s , sa , sz );
2376+ WINSOCK_RETURN ( connect (s , sa , sz ) );
22452377}
22462378
22472379#undef bind
22482380int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
22492381{
22502382 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2251- return bind (s , sa , sz );
2383+ WINSOCK_RETURN ( bind (s , sa , sz ) );
22522384}
22532385
22542386#undef setsockopt
22552387int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
22562388{
22572389 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2258- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2390+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
22592391}
22602392
22612393#undef shutdown
22622394int mingw_shutdown (int sockfd , int how )
22632395{
22642396 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2265- return shutdown (s , how );
2397+ WINSOCK_RETURN ( shutdown (s , how ) );
22662398}
22672399
22682400#undef listen
22692401int mingw_listen (int sockfd , int backlog )
22702402{
22712403 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2272- return listen (s , backlog );
2404+ WINSOCK_RETURN ( listen (s , backlog ) );
22732405}
22742406
22752407#undef accept
@@ -2280,6 +2412,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
22802412 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
22812413 SOCKET s2 = accept (s1 , sa , sz );
22822414
2415+ if (s2 == INVALID_SOCKET ) {
2416+ set_wsa_errno ();
2417+ return -1 ;
2418+ }
2419+
22832420 /* convert into a file descriptor */
22842421 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
22852422 int err = errno ;
0 commit comments