@@ -2138,26 +2138,158 @@ static void ensure_socket_initialization(void)
21382138 initialized = 1 ;
21392139}
21402140
2141+ static int winsock_error_to_errno (DWORD err )
2142+ {
2143+ switch (err ) {
2144+ case WSAEINTR : return EINTR ;
2145+ case WSAEBADF : return EBADF ;
2146+ case WSAEACCES : return EACCES ;
2147+ case WSAEFAULT : return EFAULT ;
2148+ case WSAEINVAL : return EINVAL ;
2149+ case WSAEMFILE : return EMFILE ;
2150+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2151+ case WSAEINPROGRESS : return EINPROGRESS ;
2152+ case WSAEALREADY : return EALREADY ;
2153+ case WSAENOTSOCK : return ENOTSOCK ;
2154+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2155+ case WSAEMSGSIZE : return EMSGSIZE ;
2156+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2157+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2158+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2159+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2160+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2161+ case WSAEADDRINUSE : return EADDRINUSE ;
2162+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2163+ case WSAENETDOWN : return ENETDOWN ;
2164+ case WSAENETUNREACH : return ENETUNREACH ;
2165+ case WSAENETRESET : return ENETRESET ;
2166+ case WSAECONNABORTED : return ECONNABORTED ;
2167+ case WSAECONNRESET : return ECONNRESET ;
2168+ case WSAENOBUFS : return ENOBUFS ;
2169+ case WSAEISCONN : return EISCONN ;
2170+ case WSAENOTCONN : return ENOTCONN ;
2171+ case WSAETIMEDOUT : return ETIMEDOUT ;
2172+ case WSAECONNREFUSED : return ECONNREFUSED ;
2173+ case WSAELOOP : return ELOOP ;
2174+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2175+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2176+ case WSAENOTEMPTY : return ENOTEMPTY ;
2177+ /* No errno equivalent; default to EIO */
2178+ case WSAESOCKTNOSUPPORT :
2179+ case WSAEPFNOSUPPORT :
2180+ case WSAESHUTDOWN :
2181+ case WSAETOOMANYREFS :
2182+ case WSAEHOSTDOWN :
2183+ case WSAEPROCLIM :
2184+ case WSAEUSERS :
2185+ case WSAEDQUOT :
2186+ case WSAESTALE :
2187+ case WSAEREMOTE :
2188+ case WSASYSNOTREADY :
2189+ case WSAVERNOTSUPPORTED :
2190+ case WSANOTINITIALISED :
2191+ case WSAEDISCON :
2192+ case WSAENOMORE :
2193+ case WSAECANCELLED :
2194+ case WSAEINVALIDPROCTABLE :
2195+ case WSAEINVALIDPROVIDER :
2196+ case WSAEPROVIDERFAILEDINIT :
2197+ case WSASYSCALLFAILURE :
2198+ case WSASERVICE_NOT_FOUND :
2199+ case WSATYPE_NOT_FOUND :
2200+ case WSA_E_NO_MORE :
2201+ case WSA_E_CANCELLED :
2202+ case WSAEREFUSED :
2203+ case WSAHOST_NOT_FOUND :
2204+ case WSATRY_AGAIN :
2205+ case WSANO_RECOVERY :
2206+ case WSANO_DATA :
2207+ case WSA_QOS_RECEIVERS :
2208+ case WSA_QOS_SENDERS :
2209+ case WSA_QOS_NO_SENDERS :
2210+ case WSA_QOS_NO_RECEIVERS :
2211+ case WSA_QOS_REQUEST_CONFIRMED :
2212+ case WSA_QOS_ADMISSION_FAILURE :
2213+ case WSA_QOS_POLICY_FAILURE :
2214+ case WSA_QOS_BAD_STYLE :
2215+ case WSA_QOS_BAD_OBJECT :
2216+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2217+ case WSA_QOS_GENERIC_ERROR :
2218+ case WSA_QOS_ESERVICETYPE :
2219+ case WSA_QOS_EFLOWSPEC :
2220+ case WSA_QOS_EPROVSPECBUF :
2221+ case WSA_QOS_EFILTERSTYLE :
2222+ case WSA_QOS_EFILTERTYPE :
2223+ case WSA_QOS_EFILTERCOUNT :
2224+ case WSA_QOS_EOBJLENGTH :
2225+ case WSA_QOS_EFLOWCOUNT :
2226+ #ifndef _MSC_VER
2227+ case WSA_QOS_EUNKNOWNPSOBJ :
2228+ #endif
2229+ case WSA_QOS_EPOLICYOBJ :
2230+ case WSA_QOS_EFLOWDESC :
2231+ case WSA_QOS_EPSFLOWSPEC :
2232+ case WSA_QOS_EPSFILTERSPEC :
2233+ case WSA_QOS_ESDMODEOBJ :
2234+ case WSA_QOS_ESHAPERATEOBJ :
2235+ case WSA_QOS_RESERVED_PETYPE :
2236+ default : return EIO ;
2237+ }
2238+ }
2239+
2240+ /*
2241+ * On Windows, `errno` is a global macro to a function call.
2242+ * This makes it difficult to debug and single-step our mappings.
2243+ */
2244+ static inline void set_wsa_errno (void )
2245+ {
2246+ DWORD wsa = WSAGetLastError ();
2247+ int e = winsock_error_to_errno (wsa );
2248+ errno = e ;
2249+
2250+ #ifdef DEBUG_WSA_ERRNO
2251+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2252+ fflush (stderr );
2253+ #endif
2254+ }
2255+
2256+ static inline int winsock_return (int ret )
2257+ {
2258+ if (ret < 0 )
2259+ set_wsa_errno ();
2260+
2261+ return ret ;
2262+ }
2263+
2264+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2265+
21412266#undef gethostname
21422267int mingw_gethostname (char * name , int namelen )
21432268{
2144- ensure_socket_initialization ();
2145- return gethostname (name , namelen );
2269+ ensure_socket_initialization ();
2270+ WINSOCK_RETURN ( gethostname (name , namelen ) );
21462271}
21472272
21482273#undef gethostbyname
21492274struct hostent * mingw_gethostbyname (const char * host )
21502275{
2276+ struct hostent * ret ;
2277+
21512278 ensure_socket_initialization ();
2152- return gethostbyname (host );
2279+
2280+ ret = gethostbyname (host );
2281+ if (!ret )
2282+ set_wsa_errno ();
2283+
2284+ return ret ;
21532285}
21542286
21552287#undef getaddrinfo
21562288int mingw_getaddrinfo (const char * node , const char * service ,
21572289 const struct addrinfo * hints , struct addrinfo * * res )
21582290{
21592291 ensure_socket_initialization ();
2160- return getaddrinfo (node , service , hints , res );
2292+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
21612293}
21622294
21632295int mingw_socket (int domain , int type , int protocol )
@@ -2177,7 +2309,7 @@ int mingw_socket(int domain, int type, int protocol)
21772309 * in errno so that _if_ someone looks up the code somewhere,
21782310 * then it is at least the number that are usually listed.
21792311 */
2180- errno = WSAGetLastError ();
2312+ set_wsa_errno ();
21812313 return -1 ;
21822314 }
21832315 /* convert into a file descriptor */
@@ -2193,35 +2325,35 @@ int mingw_socket(int domain, int type, int protocol)
21932325int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
21942326{
21952327 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2196- return connect (s , sa , sz );
2328+ WINSOCK_RETURN ( connect (s , sa , sz ) );
21972329}
21982330
21992331#undef bind
22002332int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
22012333{
22022334 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2203- return bind (s , sa , sz );
2335+ WINSOCK_RETURN ( bind (s , sa , sz ) );
22042336}
22052337
22062338#undef setsockopt
22072339int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
22082340{
22092341 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2210- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2342+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
22112343}
22122344
22132345#undef shutdown
22142346int mingw_shutdown (int sockfd , int how )
22152347{
22162348 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2217- return shutdown (s , how );
2349+ WINSOCK_RETURN ( shutdown (s , how ) );
22182350}
22192351
22202352#undef listen
22212353int mingw_listen (int sockfd , int backlog )
22222354{
22232355 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2224- return listen (s , backlog );
2356+ WINSOCK_RETURN ( listen (s , backlog ) );
22252357}
22262358
22272359#undef accept
@@ -2232,6 +2364,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
22322364 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
22332365 SOCKET s2 = accept (s1 , sa , sz );
22342366
2367+ if (s2 == INVALID_SOCKET ) {
2368+ set_wsa_errno ();
2369+ return -1 ;
2370+ }
2371+
22352372 /* convert into a file descriptor */
22362373 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
22372374 int err = errno ;
0 commit comments