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