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