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