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