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