@@ -2254,26 +2254,243 @@ static void ensure_socket_initialization(void)
22542254 initialized = 1 ;
22552255}
22562256
2257+ static int winsock_error_to_errno (DWORD err )
2258+ {
2259+ switch (err ) {
2260+ case WSAEINTR : return EINTR ;
2261+ case WSAEBADF : return EBADF ;
2262+ case WSAEACCES : return EACCES ;
2263+ case WSAEFAULT : return EFAULT ;
2264+ case WSAEINVAL : return EINVAL ;
2265+ case WSAEMFILE : return EMFILE ;
2266+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2267+ case WSAEINPROGRESS : return EINPROGRESS ;
2268+ case WSAEALREADY : return EALREADY ;
2269+ case WSAENOTSOCK : return ENOTSOCK ;
2270+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2271+ case WSAEMSGSIZE : return EMSGSIZE ;
2272+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2273+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2274+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2275+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2276+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2277+ case WSAEADDRINUSE : return EADDRINUSE ;
2278+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2279+ case WSAENETDOWN : return ENETDOWN ;
2280+ case WSAENETUNREACH : return ENETUNREACH ;
2281+ case WSAENETRESET : return ENETRESET ;
2282+ case WSAECONNABORTED : return ECONNABORTED ;
2283+ case WSAECONNRESET : return ECONNRESET ;
2284+ case WSAENOBUFS : return ENOBUFS ;
2285+ case WSAEISCONN : return EISCONN ;
2286+ case WSAENOTCONN : return ENOTCONN ;
2287+ case WSAETIMEDOUT : return ETIMEDOUT ;
2288+ case WSAECONNREFUSED : return ECONNREFUSED ;
2289+ case WSAELOOP : return ELOOP ;
2290+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2291+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2292+ case WSAENOTEMPTY : return ENOTEMPTY ;
2293+ /* No errno equivalent; default to EIO */
2294+ case WSAESOCKTNOSUPPORT :
2295+ case WSAEPFNOSUPPORT :
2296+ case WSAESHUTDOWN :
2297+ case WSAETOOMANYREFS :
2298+ case WSAEHOSTDOWN :
2299+ case WSAEPROCLIM :
2300+ case WSAEUSERS :
2301+ case WSAEDQUOT :
2302+ case WSAESTALE :
2303+ case WSAEREMOTE :
2304+ case WSASYSNOTREADY :
2305+ case WSAVERNOTSUPPORTED :
2306+ case WSANOTINITIALISED :
2307+ case WSAEDISCON :
2308+ case WSAENOMORE :
2309+ case WSAECANCELLED :
2310+ case WSAEINVALIDPROCTABLE :
2311+ case WSAEINVALIDPROVIDER :
2312+ case WSAEPROVIDERFAILEDINIT :
2313+ case WSASYSCALLFAILURE :
2314+ case WSASERVICE_NOT_FOUND :
2315+ case WSATYPE_NOT_FOUND :
2316+ case WSA_E_NO_MORE :
2317+ case WSA_E_CANCELLED :
2318+ case WSAEREFUSED :
2319+ case WSAHOST_NOT_FOUND :
2320+ case WSATRY_AGAIN :
2321+ case WSANO_RECOVERY :
2322+ case WSANO_DATA :
2323+ case WSA_QOS_RECEIVERS :
2324+ case WSA_QOS_SENDERS :
2325+ case WSA_QOS_NO_SENDERS :
2326+ case WSA_QOS_NO_RECEIVERS :
2327+ case WSA_QOS_REQUEST_CONFIRMED :
2328+ case WSA_QOS_ADMISSION_FAILURE :
2329+ case WSA_QOS_POLICY_FAILURE :
2330+ case WSA_QOS_BAD_STYLE :
2331+ case WSA_QOS_BAD_OBJECT :
2332+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2333+ case WSA_QOS_GENERIC_ERROR :
2334+ case WSA_QOS_ESERVICETYPE :
2335+ case WSA_QOS_EFLOWSPEC :
2336+ case WSA_QOS_EPROVSPECBUF :
2337+ case WSA_QOS_EFILTERSTYLE :
2338+ case WSA_QOS_EFILTERTYPE :
2339+ case WSA_QOS_EFILTERCOUNT :
2340+ case WSA_QOS_EOBJLENGTH :
2341+ case WSA_QOS_EFLOWCOUNT :
2342+ #ifndef _MSC_VER
2343+ case WSA_QOS_EUNKNOWNPSOBJ :
2344+ #endif
2345+ case WSA_QOS_EPOLICYOBJ :
2346+ case WSA_QOS_EFLOWDESC :
2347+ case WSA_QOS_EPSFLOWSPEC :
2348+ case WSA_QOS_EPSFILTERSPEC :
2349+ case WSA_QOS_ESDMODEOBJ :
2350+ case WSA_QOS_ESHAPERATEOBJ :
2351+ case WSA_QOS_RESERVED_PETYPE :
2352+ default : return EIO ;
2353+ }
2354+ }
2355+
2356+ /*
2357+ * On Windows, `errno` is a global macro to a function call.
2358+ * This makes it difficult to debug and single-step our mappings.
2359+ */
2360+ static inline void set_wsa_errno (void )
2361+ {
2362+ DWORD wsa = WSAGetLastError ();
2363+ int e = winsock_error_to_errno (wsa );
2364+ errno = e ;
2365+
2366+ #ifdef DEBUG_WSA_ERRNO
2367+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2368+ fflush (stderr );
2369+ #endif
2370+ }
2371+
2372+ static inline int winsock_return (int ret )
2373+ {
2374+ if (ret < 0 )
2375+ set_wsa_errno ();
2376+
2377+ return ret ;
2378+ }
2379+
2380+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2381+
2382+ #undef strerror
2383+ char * mingw_strerror (int errnum )
2384+ {
2385+ static char buf [41 ] = "" ;
2386+ switch (errnum ) {
2387+ case EWOULDBLOCK :
2388+ xsnprintf (buf , 41 , "%s" , "Operation would block" );
2389+ break ;
2390+ case EINPROGRESS :
2391+ xsnprintf (buf , 41 , "%s" , "Operation now in progress" );
2392+ break ;
2393+ case EALREADY :
2394+ xsnprintf (buf , 41 , "%s" , "Operation already in progress" );
2395+ break ;
2396+ case ENOTSOCK :
2397+ xsnprintf (buf , 41 , "%s" , "Socket operation on non-socket" );
2398+ break ;
2399+ case EDESTADDRREQ :
2400+ xsnprintf (buf , 41 , "%s" , "Destination address required" );
2401+ break ;
2402+ case EMSGSIZE :
2403+ xsnprintf (buf , 41 , "%s" , "Message too long" );
2404+ break ;
2405+ case EPROTOTYPE :
2406+ xsnprintf (buf , 41 , "%s" , "Protocol wrong type for socket" );
2407+ break ;
2408+ case ENOPROTOOPT :
2409+ xsnprintf (buf , 41 , "%s" , "Protocol not available" );
2410+ break ;
2411+ case EPROTONOSUPPORT :
2412+ xsnprintf (buf , 41 , "%s" , "Protocol not supported" );
2413+ break ;
2414+ case EOPNOTSUPP :
2415+ xsnprintf (buf , 41 , "%s" , "Operation not supported" );
2416+ break ;
2417+ case EAFNOSUPPORT :
2418+ xsnprintf (buf , 41 , "%s" , "Address family not supported by protocol" );
2419+ break ;
2420+ case EADDRINUSE :
2421+ xsnprintf (buf , 41 , "%s" , "Address already in use" );
2422+ break ;
2423+ case EADDRNOTAVAIL :
2424+ xsnprintf (buf , 41 , "%s" , "Cannot assign requested address" );
2425+ break ;
2426+ case ENETDOWN :
2427+ xsnprintf (buf , 41 , "%s" , "Network is down" );
2428+ break ;
2429+ case ENETUNREACH :
2430+ xsnprintf (buf , 41 , "%s" , "Network is unreachable" );
2431+ break ;
2432+ case ENETRESET :
2433+ xsnprintf (buf , 41 , "%s" , "Network dropped connection on reset" );
2434+ break ;
2435+ case ECONNABORTED :
2436+ xsnprintf (buf , 41 , "%s" , "Software caused connection abort" );
2437+ break ;
2438+ case ECONNRESET :
2439+ xsnprintf (buf , 41 , "%s" , "Connection reset by peer" );
2440+ break ;
2441+ case ENOBUFS :
2442+ xsnprintf (buf , 41 , "%s" , "No buffer space available" );
2443+ break ;
2444+ case EISCONN :
2445+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is already connected" );
2446+ break ;
2447+ case ENOTCONN :
2448+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is not connected" );
2449+ break ;
2450+ case ETIMEDOUT :
2451+ xsnprintf (buf , 41 , "%s" , "Connection timed out" );
2452+ break ;
2453+ case ECONNREFUSED :
2454+ xsnprintf (buf , 41 , "%s" , "Connection refused" );
2455+ break ;
2456+ case ELOOP :
2457+ xsnprintf (buf , 41 , "%s" , "Too many levels of symbolic links" );
2458+ break ;
2459+ case EHOSTUNREACH :
2460+ xsnprintf (buf , 41 , "%s" , "No route to host" );
2461+ break ;
2462+ default : return strerror (errnum );
2463+ }
2464+ return buf ;
2465+ }
2466+
22572467#undef gethostname
22582468int mingw_gethostname (char * name , int namelen )
22592469{
2260- ensure_socket_initialization ();
2261- return gethostname (name , namelen );
2470+ ensure_socket_initialization ();
2471+ WINSOCK_RETURN ( gethostname (name , namelen ) );
22622472}
22632473
22642474#undef gethostbyname
22652475struct hostent * mingw_gethostbyname (const char * host )
22662476{
2477+ struct hostent * ret ;
2478+
22672479 ensure_socket_initialization ();
2268- return gethostbyname (host );
2480+
2481+ ret = gethostbyname (host );
2482+ if (!ret )
2483+ set_wsa_errno ();
2484+
2485+ return ret ;
22692486}
22702487
22712488#undef getaddrinfo
22722489int mingw_getaddrinfo (const char * node , const char * service ,
22732490 const struct addrinfo * hints , struct addrinfo * * res )
22742491{
22752492 ensure_socket_initialization ();
2276- return getaddrinfo (node , service , hints , res );
2493+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
22772494}
22782495
22792496int mingw_socket (int domain , int type , int protocol )
@@ -2284,16 +2501,7 @@ int mingw_socket(int domain, int type, int protocol)
22842501 ensure_socket_initialization ();
22852502 s = WSASocket (domain , type , protocol , NULL , 0 , 0 );
22862503 if (s == INVALID_SOCKET ) {
2287- /*
2288- * WSAGetLastError() values are regular BSD error codes
2289- * biased by WSABASEERR.
2290- * However, strerror() does not know about networking
2291- * specific errors, which are values beginning at 38 or so.
2292- * Therefore, we choose to leave the biased error code
2293- * in errno so that _if_ someone looks up the code somewhere,
2294- * then it is at least the number that are usually listed.
2295- */
2296- errno = WSAGetLastError ();
2504+ set_wsa_errno ();
22972505 return -1 ;
22982506 }
22992507 /* convert into a file descriptor */
@@ -2309,35 +2517,35 @@ int mingw_socket(int domain, int type, int protocol)
23092517int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
23102518{
23112519 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2312- return connect (s , sa , sz );
2520+ WINSOCK_RETURN ( connect (s , sa , sz ) );
23132521}
23142522
23152523#undef bind
23162524int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
23172525{
23182526 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2319- return bind (s , sa , sz );
2527+ WINSOCK_RETURN ( bind (s , sa , sz ) );
23202528}
23212529
23222530#undef setsockopt
23232531int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
23242532{
23252533 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2326- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2534+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
23272535}
23282536
23292537#undef shutdown
23302538int mingw_shutdown (int sockfd , int how )
23312539{
23322540 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2333- return shutdown (s , how );
2541+ WINSOCK_RETURN ( shutdown (s , how ) );
23342542}
23352543
23362544#undef listen
23372545int mingw_listen (int sockfd , int backlog )
23382546{
23392547 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2340- return listen (s , backlog );
2548+ WINSOCK_RETURN ( listen (s , backlog ) );
23412549}
23422550
23432551#undef accept
@@ -2348,6 +2556,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
23482556 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
23492557 SOCKET s2 = accept (s1 , sa , sz );
23502558
2559+ if (s2 == INVALID_SOCKET ) {
2560+ set_wsa_errno ();
2561+ return -1 ;
2562+ }
2563+
23512564 /* convert into a file descriptor */
23522565 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
23532566 int err = errno ;
0 commit comments