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