@@ -2091,26 +2091,158 @@ static void ensure_socket_initialization(void)
20912091 initialized = 1 ;
20922092}
20932093
2094+ static int winsock_error_to_errno (DWORD err )
2095+ {
2096+ switch (err ) {
2097+ case WSAEINTR : return EINTR ;
2098+ case WSAEBADF : return EBADF ;
2099+ case WSAEACCES : return EACCES ;
2100+ case WSAEFAULT : return EFAULT ;
2101+ case WSAEINVAL : return EINVAL ;
2102+ case WSAEMFILE : return EMFILE ;
2103+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2104+ case WSAEINPROGRESS : return EINPROGRESS ;
2105+ case WSAEALREADY : return EALREADY ;
2106+ case WSAENOTSOCK : return ENOTSOCK ;
2107+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2108+ case WSAEMSGSIZE : return EMSGSIZE ;
2109+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2110+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2111+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2112+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2113+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2114+ case WSAEADDRINUSE : return EADDRINUSE ;
2115+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2116+ case WSAENETDOWN : return ENETDOWN ;
2117+ case WSAENETUNREACH : return ENETUNREACH ;
2118+ case WSAENETRESET : return ENETRESET ;
2119+ case WSAECONNABORTED : return ECONNABORTED ;
2120+ case WSAECONNRESET : return ECONNRESET ;
2121+ case WSAENOBUFS : return ENOBUFS ;
2122+ case WSAEISCONN : return EISCONN ;
2123+ case WSAENOTCONN : return ENOTCONN ;
2124+ case WSAETIMEDOUT : return ETIMEDOUT ;
2125+ case WSAECONNREFUSED : return ECONNREFUSED ;
2126+ case WSAELOOP : return ELOOP ;
2127+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2128+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2129+ case WSAENOTEMPTY : return ENOTEMPTY ;
2130+ /* No errno equivalent; default to EIO */
2131+ case WSAESOCKTNOSUPPORT :
2132+ case WSAEPFNOSUPPORT :
2133+ case WSAESHUTDOWN :
2134+ case WSAETOOMANYREFS :
2135+ case WSAEHOSTDOWN :
2136+ case WSAEPROCLIM :
2137+ case WSAEUSERS :
2138+ case WSAEDQUOT :
2139+ case WSAESTALE :
2140+ case WSAEREMOTE :
2141+ case WSASYSNOTREADY :
2142+ case WSAVERNOTSUPPORTED :
2143+ case WSANOTINITIALISED :
2144+ case WSAEDISCON :
2145+ case WSAENOMORE :
2146+ case WSAECANCELLED :
2147+ case WSAEINVALIDPROCTABLE :
2148+ case WSAEINVALIDPROVIDER :
2149+ case WSAEPROVIDERFAILEDINIT :
2150+ case WSASYSCALLFAILURE :
2151+ case WSASERVICE_NOT_FOUND :
2152+ case WSATYPE_NOT_FOUND :
2153+ case WSA_E_NO_MORE :
2154+ case WSA_E_CANCELLED :
2155+ case WSAEREFUSED :
2156+ case WSAHOST_NOT_FOUND :
2157+ case WSATRY_AGAIN :
2158+ case WSANO_RECOVERY :
2159+ case WSANO_DATA :
2160+ case WSA_QOS_RECEIVERS :
2161+ case WSA_QOS_SENDERS :
2162+ case WSA_QOS_NO_SENDERS :
2163+ case WSA_QOS_NO_RECEIVERS :
2164+ case WSA_QOS_REQUEST_CONFIRMED :
2165+ case WSA_QOS_ADMISSION_FAILURE :
2166+ case WSA_QOS_POLICY_FAILURE :
2167+ case WSA_QOS_BAD_STYLE :
2168+ case WSA_QOS_BAD_OBJECT :
2169+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2170+ case WSA_QOS_GENERIC_ERROR :
2171+ case WSA_QOS_ESERVICETYPE :
2172+ case WSA_QOS_EFLOWSPEC :
2173+ case WSA_QOS_EPROVSPECBUF :
2174+ case WSA_QOS_EFILTERSTYLE :
2175+ case WSA_QOS_EFILTERTYPE :
2176+ case WSA_QOS_EFILTERCOUNT :
2177+ case WSA_QOS_EOBJLENGTH :
2178+ case WSA_QOS_EFLOWCOUNT :
2179+ #ifndef _MSC_VER
2180+ case WSA_QOS_EUNKNOWNPSOBJ :
2181+ #endif
2182+ case WSA_QOS_EPOLICYOBJ :
2183+ case WSA_QOS_EFLOWDESC :
2184+ case WSA_QOS_EPSFLOWSPEC :
2185+ case WSA_QOS_EPSFILTERSPEC :
2186+ case WSA_QOS_ESDMODEOBJ :
2187+ case WSA_QOS_ESHAPERATEOBJ :
2188+ case WSA_QOS_RESERVED_PETYPE :
2189+ default : return EIO ;
2190+ }
2191+ }
2192+
2193+ /*
2194+ * On Windows, `errno` is a global macro to a function call.
2195+ * This makes it difficult to debug and single-step our mappings.
2196+ */
2197+ static inline void set_wsa_errno (void )
2198+ {
2199+ DWORD wsa = WSAGetLastError ();
2200+ int e = winsock_error_to_errno (wsa );
2201+ errno = e ;
2202+
2203+ #ifdef DEBUG_WSA_ERRNO
2204+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2205+ fflush (stderr );
2206+ #endif
2207+ }
2208+
2209+ static inline int winsock_return (int ret )
2210+ {
2211+ if (ret < 0 )
2212+ set_wsa_errno ();
2213+
2214+ return ret ;
2215+ }
2216+
2217+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2218+
20942219#undef gethostname
20952220int mingw_gethostname (char * name , int namelen )
20962221{
2097- ensure_socket_initialization ();
2098- return gethostname (name , namelen );
2222+ ensure_socket_initialization ();
2223+ WINSOCK_RETURN ( gethostname (name , namelen ) );
20992224}
21002225
21012226#undef gethostbyname
21022227struct hostent * mingw_gethostbyname (const char * host )
21032228{
2229+ struct hostent * ret ;
2230+
21042231 ensure_socket_initialization ();
2105- return gethostbyname (host );
2232+
2233+ ret = gethostbyname (host );
2234+ if (!ret )
2235+ set_wsa_errno ();
2236+
2237+ return ret ;
21062238}
21072239
21082240#undef getaddrinfo
21092241int mingw_getaddrinfo (const char * node , const char * service ,
21102242 const struct addrinfo * hints , struct addrinfo * * res )
21112243{
21122244 ensure_socket_initialization ();
2113- return getaddrinfo (node , service , hints , res );
2245+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
21142246}
21152247
21162248int mingw_socket (int domain , int type , int protocol )
@@ -2130,7 +2262,7 @@ int mingw_socket(int domain, int type, int protocol)
21302262 * in errno so that _if_ someone looks up the code somewhere,
21312263 * then it is at least the number that are usually listed.
21322264 */
2133- errno = WSAGetLastError ();
2265+ set_wsa_errno ();
21342266 return -1 ;
21352267 }
21362268 /* convert into a file descriptor */
@@ -2146,35 +2278,35 @@ int mingw_socket(int domain, int type, int protocol)
21462278int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
21472279{
21482280 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2149- return connect (s , sa , sz );
2281+ WINSOCK_RETURN ( connect (s , sa , sz ) );
21502282}
21512283
21522284#undef bind
21532285int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
21542286{
21552287 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2156- return bind (s , sa , sz );
2288+ WINSOCK_RETURN ( bind (s , sa , sz ) );
21572289}
21582290
21592291#undef setsockopt
21602292int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
21612293{
21622294 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2163- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2295+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
21642296}
21652297
21662298#undef shutdown
21672299int mingw_shutdown (int sockfd , int how )
21682300{
21692301 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2170- return shutdown (s , how );
2302+ WINSOCK_RETURN ( shutdown (s , how ) );
21712303}
21722304
21732305#undef listen
21742306int mingw_listen (int sockfd , int backlog )
21752307{
21762308 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2177- return listen (s , backlog );
2309+ WINSOCK_RETURN ( listen (s , backlog ) );
21782310}
21792311
21802312#undef accept
@@ -2185,6 +2317,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
21852317 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
21862318 SOCKET s2 = accept (s1 , sa , sz );
21872319
2320+ if (s2 == INVALID_SOCKET ) {
2321+ set_wsa_errno ();
2322+ return -1 ;
2323+ }
2324+
21882325 /* convert into a file descriptor */
21892326 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
21902327 int err = errno ;
0 commit comments