@@ -2118,26 +2118,158 @@ static void ensure_socket_initialization(void)
21182118 initialized = 1 ;
21192119}
21202120
2121+ static int winsock_error_to_errno (DWORD err )
2122+ {
2123+ switch (err ) {
2124+ case WSAEINTR : return EINTR ;
2125+ case WSAEBADF : return EBADF ;
2126+ case WSAEACCES : return EACCES ;
2127+ case WSAEFAULT : return EFAULT ;
2128+ case WSAEINVAL : return EINVAL ;
2129+ case WSAEMFILE : return EMFILE ;
2130+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2131+ case WSAEINPROGRESS : return EINPROGRESS ;
2132+ case WSAEALREADY : return EALREADY ;
2133+ case WSAENOTSOCK : return ENOTSOCK ;
2134+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2135+ case WSAEMSGSIZE : return EMSGSIZE ;
2136+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2137+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2138+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2139+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2140+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2141+ case WSAEADDRINUSE : return EADDRINUSE ;
2142+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2143+ case WSAENETDOWN : return ENETDOWN ;
2144+ case WSAENETUNREACH : return ENETUNREACH ;
2145+ case WSAENETRESET : return ENETRESET ;
2146+ case WSAECONNABORTED : return ECONNABORTED ;
2147+ case WSAECONNRESET : return ECONNRESET ;
2148+ case WSAENOBUFS : return ENOBUFS ;
2149+ case WSAEISCONN : return EISCONN ;
2150+ case WSAENOTCONN : return ENOTCONN ;
2151+ case WSAETIMEDOUT : return ETIMEDOUT ;
2152+ case WSAECONNREFUSED : return ECONNREFUSED ;
2153+ case WSAELOOP : return ELOOP ;
2154+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2155+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2156+ case WSAENOTEMPTY : return ENOTEMPTY ;
2157+ /* No errno equivalent; default to EIO */
2158+ case WSAESOCKTNOSUPPORT :
2159+ case WSAEPFNOSUPPORT :
2160+ case WSAESHUTDOWN :
2161+ case WSAETOOMANYREFS :
2162+ case WSAEHOSTDOWN :
2163+ case WSAEPROCLIM :
2164+ case WSAEUSERS :
2165+ case WSAEDQUOT :
2166+ case WSAESTALE :
2167+ case WSAEREMOTE :
2168+ case WSASYSNOTREADY :
2169+ case WSAVERNOTSUPPORTED :
2170+ case WSANOTINITIALISED :
2171+ case WSAEDISCON :
2172+ case WSAENOMORE :
2173+ case WSAECANCELLED :
2174+ case WSAEINVALIDPROCTABLE :
2175+ case WSAEINVALIDPROVIDER :
2176+ case WSAEPROVIDERFAILEDINIT :
2177+ case WSASYSCALLFAILURE :
2178+ case WSASERVICE_NOT_FOUND :
2179+ case WSATYPE_NOT_FOUND :
2180+ case WSA_E_NO_MORE :
2181+ case WSA_E_CANCELLED :
2182+ case WSAEREFUSED :
2183+ case WSAHOST_NOT_FOUND :
2184+ case WSATRY_AGAIN :
2185+ case WSANO_RECOVERY :
2186+ case WSANO_DATA :
2187+ case WSA_QOS_RECEIVERS :
2188+ case WSA_QOS_SENDERS :
2189+ case WSA_QOS_NO_SENDERS :
2190+ case WSA_QOS_NO_RECEIVERS :
2191+ case WSA_QOS_REQUEST_CONFIRMED :
2192+ case WSA_QOS_ADMISSION_FAILURE :
2193+ case WSA_QOS_POLICY_FAILURE :
2194+ case WSA_QOS_BAD_STYLE :
2195+ case WSA_QOS_BAD_OBJECT :
2196+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2197+ case WSA_QOS_GENERIC_ERROR :
2198+ case WSA_QOS_ESERVICETYPE :
2199+ case WSA_QOS_EFLOWSPEC :
2200+ case WSA_QOS_EPROVSPECBUF :
2201+ case WSA_QOS_EFILTERSTYLE :
2202+ case WSA_QOS_EFILTERTYPE :
2203+ case WSA_QOS_EFILTERCOUNT :
2204+ case WSA_QOS_EOBJLENGTH :
2205+ case WSA_QOS_EFLOWCOUNT :
2206+ #ifndef _MSC_VER
2207+ case WSA_QOS_EUNKNOWNPSOBJ :
2208+ #endif
2209+ case WSA_QOS_EPOLICYOBJ :
2210+ case WSA_QOS_EFLOWDESC :
2211+ case WSA_QOS_EPSFLOWSPEC :
2212+ case WSA_QOS_EPSFILTERSPEC :
2213+ case WSA_QOS_ESDMODEOBJ :
2214+ case WSA_QOS_ESHAPERATEOBJ :
2215+ case WSA_QOS_RESERVED_PETYPE :
2216+ default : return EIO ;
2217+ }
2218+ }
2219+
2220+ /*
2221+ * On Windows, `errno` is a global macro to a function call.
2222+ * This makes it difficult to debug and single-step our mappings.
2223+ */
2224+ static inline void set_wsa_errno (void )
2225+ {
2226+ DWORD wsa = WSAGetLastError ();
2227+ int e = winsock_error_to_errno (wsa );
2228+ errno = e ;
2229+
2230+ #ifdef DEBUG_WSA_ERRNO
2231+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2232+ fflush (stderr );
2233+ #endif
2234+ }
2235+
2236+ static inline int winsock_return (int ret )
2237+ {
2238+ if (ret < 0 )
2239+ set_wsa_errno ();
2240+
2241+ return ret ;
2242+ }
2243+
2244+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2245+
21212246#undef gethostname
21222247int mingw_gethostname (char * name , int namelen )
21232248{
2124- ensure_socket_initialization ();
2125- return gethostname (name , namelen );
2249+ ensure_socket_initialization ();
2250+ WINSOCK_RETURN ( gethostname (name , namelen ) );
21262251}
21272252
21282253#undef gethostbyname
21292254struct hostent * mingw_gethostbyname (const char * host )
21302255{
2256+ struct hostent * ret ;
2257+
21312258 ensure_socket_initialization ();
2132- return gethostbyname (host );
2259+
2260+ ret = gethostbyname (host );
2261+ if (!ret )
2262+ set_wsa_errno ();
2263+
2264+ return ret ;
21332265}
21342266
21352267#undef getaddrinfo
21362268int mingw_getaddrinfo (const char * node , const char * service ,
21372269 const struct addrinfo * hints , struct addrinfo * * res )
21382270{
21392271 ensure_socket_initialization ();
2140- return getaddrinfo (node , service , hints , res );
2272+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
21412273}
21422274
21432275int mingw_socket (int domain , int type , int protocol )
@@ -2157,7 +2289,7 @@ int mingw_socket(int domain, int type, int protocol)
21572289 * in errno so that _if_ someone looks up the code somewhere,
21582290 * then it is at least the number that are usually listed.
21592291 */
2160- errno = WSAGetLastError ();
2292+ set_wsa_errno ();
21612293 return -1 ;
21622294 }
21632295 /* convert into a file descriptor */
@@ -2173,35 +2305,35 @@ int mingw_socket(int domain, int type, int protocol)
21732305int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
21742306{
21752307 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2176- return connect (s , sa , sz );
2308+ WINSOCK_RETURN ( connect (s , sa , sz ) );
21772309}
21782310
21792311#undef bind
21802312int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
21812313{
21822314 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2183- return bind (s , sa , sz );
2315+ WINSOCK_RETURN ( bind (s , sa , sz ) );
21842316}
21852317
21862318#undef setsockopt
21872319int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
21882320{
21892321 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2190- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2322+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
21912323}
21922324
21932325#undef shutdown
21942326int mingw_shutdown (int sockfd , int how )
21952327{
21962328 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2197- return shutdown (s , how );
2329+ WINSOCK_RETURN ( shutdown (s , how ) );
21982330}
21992331
22002332#undef listen
22012333int mingw_listen (int sockfd , int backlog )
22022334{
22032335 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2204- return listen (s , backlog );
2336+ WINSOCK_RETURN ( listen (s , backlog ) );
22052337}
22062338
22072339#undef accept
@@ -2212,6 +2344,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
22122344 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
22132345 SOCKET s2 = accept (s1 , sa , sz );
22142346
2347+ if (s2 == INVALID_SOCKET ) {
2348+ set_wsa_errno ();
2349+ return -1 ;
2350+ }
2351+
22152352 /* convert into a file descriptor */
22162353 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
22172354 int err = errno ;
0 commit comments