@@ -2187,26 +2187,243 @@ static void ensure_socket_initialization(void)
21872187 initialized = 1 ;
21882188}
21892189
2190+ static int winsock_error_to_errno (DWORD err )
2191+ {
2192+ switch (err ) {
2193+ case WSAEINTR : return EINTR ;
2194+ case WSAEBADF : return EBADF ;
2195+ case WSAEACCES : return EACCES ;
2196+ case WSAEFAULT : return EFAULT ;
2197+ case WSAEINVAL : return EINVAL ;
2198+ case WSAEMFILE : return EMFILE ;
2199+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2200+ case WSAEINPROGRESS : return EINPROGRESS ;
2201+ case WSAEALREADY : return EALREADY ;
2202+ case WSAENOTSOCK : return ENOTSOCK ;
2203+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2204+ case WSAEMSGSIZE : return EMSGSIZE ;
2205+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2206+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2207+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2208+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2209+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2210+ case WSAEADDRINUSE : return EADDRINUSE ;
2211+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2212+ case WSAENETDOWN : return ENETDOWN ;
2213+ case WSAENETUNREACH : return ENETUNREACH ;
2214+ case WSAENETRESET : return ENETRESET ;
2215+ case WSAECONNABORTED : return ECONNABORTED ;
2216+ case WSAECONNRESET : return ECONNRESET ;
2217+ case WSAENOBUFS : return ENOBUFS ;
2218+ case WSAEISCONN : return EISCONN ;
2219+ case WSAENOTCONN : return ENOTCONN ;
2220+ case WSAETIMEDOUT : return ETIMEDOUT ;
2221+ case WSAECONNREFUSED : return ECONNREFUSED ;
2222+ case WSAELOOP : return ELOOP ;
2223+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2224+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2225+ case WSAENOTEMPTY : return ENOTEMPTY ;
2226+ /* No errno equivalent; default to EIO */
2227+ case WSAESOCKTNOSUPPORT :
2228+ case WSAEPFNOSUPPORT :
2229+ case WSAESHUTDOWN :
2230+ case WSAETOOMANYREFS :
2231+ case WSAEHOSTDOWN :
2232+ case WSAEPROCLIM :
2233+ case WSAEUSERS :
2234+ case WSAEDQUOT :
2235+ case WSAESTALE :
2236+ case WSAEREMOTE :
2237+ case WSASYSNOTREADY :
2238+ case WSAVERNOTSUPPORTED :
2239+ case WSANOTINITIALISED :
2240+ case WSAEDISCON :
2241+ case WSAENOMORE :
2242+ case WSAECANCELLED :
2243+ case WSAEINVALIDPROCTABLE :
2244+ case WSAEINVALIDPROVIDER :
2245+ case WSAEPROVIDERFAILEDINIT :
2246+ case WSASYSCALLFAILURE :
2247+ case WSASERVICE_NOT_FOUND :
2248+ case WSATYPE_NOT_FOUND :
2249+ case WSA_E_NO_MORE :
2250+ case WSA_E_CANCELLED :
2251+ case WSAEREFUSED :
2252+ case WSAHOST_NOT_FOUND :
2253+ case WSATRY_AGAIN :
2254+ case WSANO_RECOVERY :
2255+ case WSANO_DATA :
2256+ case WSA_QOS_RECEIVERS :
2257+ case WSA_QOS_SENDERS :
2258+ case WSA_QOS_NO_SENDERS :
2259+ case WSA_QOS_NO_RECEIVERS :
2260+ case WSA_QOS_REQUEST_CONFIRMED :
2261+ case WSA_QOS_ADMISSION_FAILURE :
2262+ case WSA_QOS_POLICY_FAILURE :
2263+ case WSA_QOS_BAD_STYLE :
2264+ case WSA_QOS_BAD_OBJECT :
2265+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2266+ case WSA_QOS_GENERIC_ERROR :
2267+ case WSA_QOS_ESERVICETYPE :
2268+ case WSA_QOS_EFLOWSPEC :
2269+ case WSA_QOS_EPROVSPECBUF :
2270+ case WSA_QOS_EFILTERSTYLE :
2271+ case WSA_QOS_EFILTERTYPE :
2272+ case WSA_QOS_EFILTERCOUNT :
2273+ case WSA_QOS_EOBJLENGTH :
2274+ case WSA_QOS_EFLOWCOUNT :
2275+ #ifndef _MSC_VER
2276+ case WSA_QOS_EUNKNOWNPSOBJ :
2277+ #endif
2278+ case WSA_QOS_EPOLICYOBJ :
2279+ case WSA_QOS_EFLOWDESC :
2280+ case WSA_QOS_EPSFLOWSPEC :
2281+ case WSA_QOS_EPSFILTERSPEC :
2282+ case WSA_QOS_ESDMODEOBJ :
2283+ case WSA_QOS_ESHAPERATEOBJ :
2284+ case WSA_QOS_RESERVED_PETYPE :
2285+ default : return EIO ;
2286+ }
2287+ }
2288+
2289+ /*
2290+ * On Windows, `errno` is a global macro to a function call.
2291+ * This makes it difficult to debug and single-step our mappings.
2292+ */
2293+ static inline void set_wsa_errno (void )
2294+ {
2295+ DWORD wsa = WSAGetLastError ();
2296+ int e = winsock_error_to_errno (wsa );
2297+ errno = e ;
2298+
2299+ #ifdef DEBUG_WSA_ERRNO
2300+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2301+ fflush (stderr );
2302+ #endif
2303+ }
2304+
2305+ static inline int winsock_return (int ret )
2306+ {
2307+ if (ret < 0 )
2308+ set_wsa_errno ();
2309+
2310+ return ret ;
2311+ }
2312+
2313+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2314+
2315+ #undef strerror
2316+ char * mingw_strerror (int errnum )
2317+ {
2318+ static char buf [41 ] = "" ;
2319+ switch (errnum ) {
2320+ case EWOULDBLOCK :
2321+ xsnprintf (buf , 41 , "%s" , "Operation would block" );
2322+ break ;
2323+ case EINPROGRESS :
2324+ xsnprintf (buf , 41 , "%s" , "Operation now in progress" );
2325+ break ;
2326+ case EALREADY :
2327+ xsnprintf (buf , 41 , "%s" , "Operation already in progress" );
2328+ break ;
2329+ case ENOTSOCK :
2330+ xsnprintf (buf , 41 , "%s" , "Socket operation on non-socket" );
2331+ break ;
2332+ case EDESTADDRREQ :
2333+ xsnprintf (buf , 41 , "%s" , "Destination address required" );
2334+ break ;
2335+ case EMSGSIZE :
2336+ xsnprintf (buf , 41 , "%s" , "Message too long" );
2337+ break ;
2338+ case EPROTOTYPE :
2339+ xsnprintf (buf , 41 , "%s" , "Protocol wrong type for socket" );
2340+ break ;
2341+ case ENOPROTOOPT :
2342+ xsnprintf (buf , 41 , "%s" , "Protocol not available" );
2343+ break ;
2344+ case EPROTONOSUPPORT :
2345+ xsnprintf (buf , 41 , "%s" , "Protocol not supported" );
2346+ break ;
2347+ case EOPNOTSUPP :
2348+ xsnprintf (buf , 41 , "%s" , "Operation not supported" );
2349+ break ;
2350+ case EAFNOSUPPORT :
2351+ xsnprintf (buf , 41 , "%s" , "Address family not supported by protocol" );
2352+ break ;
2353+ case EADDRINUSE :
2354+ xsnprintf (buf , 41 , "%s" , "Address already in use" );
2355+ break ;
2356+ case EADDRNOTAVAIL :
2357+ xsnprintf (buf , 41 , "%s" , "Cannot assign requested address" );
2358+ break ;
2359+ case ENETDOWN :
2360+ xsnprintf (buf , 41 , "%s" , "Network is down" );
2361+ break ;
2362+ case ENETUNREACH :
2363+ xsnprintf (buf , 41 , "%s" , "Network is unreachable" );
2364+ break ;
2365+ case ENETRESET :
2366+ xsnprintf (buf , 41 , "%s" , "Network dropped connection on reset" );
2367+ break ;
2368+ case ECONNABORTED :
2369+ xsnprintf (buf , 41 , "%s" , "Software caused connection abort" );
2370+ break ;
2371+ case ECONNRESET :
2372+ xsnprintf (buf , 41 , "%s" , "Connection reset by peer" );
2373+ break ;
2374+ case ENOBUFS :
2375+ xsnprintf (buf , 41 , "%s" , "No buffer space available" );
2376+ break ;
2377+ case EISCONN :
2378+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is already connected" );
2379+ break ;
2380+ case ENOTCONN :
2381+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is not connected" );
2382+ break ;
2383+ case ETIMEDOUT :
2384+ xsnprintf (buf , 41 , "%s" , "Connection timed out" );
2385+ break ;
2386+ case ECONNREFUSED :
2387+ xsnprintf (buf , 41 , "%s" , "Connection refused" );
2388+ break ;
2389+ case ELOOP :
2390+ xsnprintf (buf , 41 , "%s" , "Too many levels of symbolic links" );
2391+ break ;
2392+ case EHOSTUNREACH :
2393+ xsnprintf (buf , 41 , "%s" , "No route to host" );
2394+ break ;
2395+ default : return strerror (errnum );
2396+ }
2397+ return buf ;
2398+ }
2399+
21902400#undef gethostname
21912401int mingw_gethostname (char * name , int namelen )
21922402{
2193- ensure_socket_initialization ();
2194- return gethostname (name , namelen );
2403+ ensure_socket_initialization ();
2404+ WINSOCK_RETURN ( gethostname (name , namelen ) );
21952405}
21962406
21972407#undef gethostbyname
21982408struct hostent * mingw_gethostbyname (const char * host )
21992409{
2410+ struct hostent * ret ;
2411+
22002412 ensure_socket_initialization ();
2201- return gethostbyname (host );
2413+
2414+ ret = gethostbyname (host );
2415+ if (!ret )
2416+ set_wsa_errno ();
2417+
2418+ return ret ;
22022419}
22032420
22042421#undef getaddrinfo
22052422int mingw_getaddrinfo (const char * node , const char * service ,
22062423 const struct addrinfo * hints , struct addrinfo * * res )
22072424{
22082425 ensure_socket_initialization ();
2209- return getaddrinfo (node , service , hints , res );
2426+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
22102427}
22112428
22122429int mingw_socket (int domain , int type , int protocol )
@@ -2217,16 +2434,7 @@ int mingw_socket(int domain, int type, int protocol)
22172434 ensure_socket_initialization ();
22182435 s = WSASocket (domain , type , protocol , NULL , 0 , 0 );
22192436 if (s == INVALID_SOCKET ) {
2220- /*
2221- * WSAGetLastError() values are regular BSD error codes
2222- * biased by WSABASEERR.
2223- * However, strerror() does not know about networking
2224- * specific errors, which are values beginning at 38 or so.
2225- * Therefore, we choose to leave the biased error code
2226- * in errno so that _if_ someone looks up the code somewhere,
2227- * then it is at least the number that are usually listed.
2228- */
2229- errno = WSAGetLastError ();
2437+ set_wsa_errno ();
22302438 return -1 ;
22312439 }
22322440 /* convert into a file descriptor */
@@ -2242,35 +2450,35 @@ int mingw_socket(int domain, int type, int protocol)
22422450int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
22432451{
22442452 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2245- return connect (s , sa , sz );
2453+ WINSOCK_RETURN ( connect (s , sa , sz ) );
22462454}
22472455
22482456#undef bind
22492457int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
22502458{
22512459 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2252- return bind (s , sa , sz );
2460+ WINSOCK_RETURN ( bind (s , sa , sz ) );
22532461}
22542462
22552463#undef setsockopt
22562464int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
22572465{
22582466 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2259- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2467+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
22602468}
22612469
22622470#undef shutdown
22632471int mingw_shutdown (int sockfd , int how )
22642472{
22652473 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2266- return shutdown (s , how );
2474+ WINSOCK_RETURN ( shutdown (s , how ) );
22672475}
22682476
22692477#undef listen
22702478int mingw_listen (int sockfd , int backlog )
22712479{
22722480 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2273- return listen (s , backlog );
2481+ WINSOCK_RETURN ( listen (s , backlog ) );
22742482}
22752483
22762484#undef accept
@@ -2281,6 +2489,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
22812489 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
22822490 SOCKET s2 = accept (s1 , sa , sz );
22832491
2492+ if (s2 == INVALID_SOCKET ) {
2493+ set_wsa_errno ();
2494+ return -1 ;
2495+ }
2496+
22842497 /* convert into a file descriptor */
22852498 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
22862499 int err = errno ;
0 commit comments