@@ -2231,26 +2231,243 @@ static void ensure_socket_initialization(void)
22312231 initialized = 1 ;
22322232}
22332233
2234+ static int winsock_error_to_errno (DWORD err )
2235+ {
2236+ switch (err ) {
2237+ case WSAEINTR : return EINTR ;
2238+ case WSAEBADF : return EBADF ;
2239+ case WSAEACCES : return EACCES ;
2240+ case WSAEFAULT : return EFAULT ;
2241+ case WSAEINVAL : return EINVAL ;
2242+ case WSAEMFILE : return EMFILE ;
2243+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2244+ case WSAEINPROGRESS : return EINPROGRESS ;
2245+ case WSAEALREADY : return EALREADY ;
2246+ case WSAENOTSOCK : return ENOTSOCK ;
2247+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2248+ case WSAEMSGSIZE : return EMSGSIZE ;
2249+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2250+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2251+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2252+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2253+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2254+ case WSAEADDRINUSE : return EADDRINUSE ;
2255+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2256+ case WSAENETDOWN : return ENETDOWN ;
2257+ case WSAENETUNREACH : return ENETUNREACH ;
2258+ case WSAENETRESET : return ENETRESET ;
2259+ case WSAECONNABORTED : return ECONNABORTED ;
2260+ case WSAECONNRESET : return ECONNRESET ;
2261+ case WSAENOBUFS : return ENOBUFS ;
2262+ case WSAEISCONN : return EISCONN ;
2263+ case WSAENOTCONN : return ENOTCONN ;
2264+ case WSAETIMEDOUT : return ETIMEDOUT ;
2265+ case WSAECONNREFUSED : return ECONNREFUSED ;
2266+ case WSAELOOP : return ELOOP ;
2267+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2268+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2269+ case WSAENOTEMPTY : return ENOTEMPTY ;
2270+ /* No errno equivalent; default to EIO */
2271+ case WSAESOCKTNOSUPPORT :
2272+ case WSAEPFNOSUPPORT :
2273+ case WSAESHUTDOWN :
2274+ case WSAETOOMANYREFS :
2275+ case WSAEHOSTDOWN :
2276+ case WSAEPROCLIM :
2277+ case WSAEUSERS :
2278+ case WSAEDQUOT :
2279+ case WSAESTALE :
2280+ case WSAEREMOTE :
2281+ case WSASYSNOTREADY :
2282+ case WSAVERNOTSUPPORTED :
2283+ case WSANOTINITIALISED :
2284+ case WSAEDISCON :
2285+ case WSAENOMORE :
2286+ case WSAECANCELLED :
2287+ case WSAEINVALIDPROCTABLE :
2288+ case WSAEINVALIDPROVIDER :
2289+ case WSAEPROVIDERFAILEDINIT :
2290+ case WSASYSCALLFAILURE :
2291+ case WSASERVICE_NOT_FOUND :
2292+ case WSATYPE_NOT_FOUND :
2293+ case WSA_E_NO_MORE :
2294+ case WSA_E_CANCELLED :
2295+ case WSAEREFUSED :
2296+ case WSAHOST_NOT_FOUND :
2297+ case WSATRY_AGAIN :
2298+ case WSANO_RECOVERY :
2299+ case WSANO_DATA :
2300+ case WSA_QOS_RECEIVERS :
2301+ case WSA_QOS_SENDERS :
2302+ case WSA_QOS_NO_SENDERS :
2303+ case WSA_QOS_NO_RECEIVERS :
2304+ case WSA_QOS_REQUEST_CONFIRMED :
2305+ case WSA_QOS_ADMISSION_FAILURE :
2306+ case WSA_QOS_POLICY_FAILURE :
2307+ case WSA_QOS_BAD_STYLE :
2308+ case WSA_QOS_BAD_OBJECT :
2309+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2310+ case WSA_QOS_GENERIC_ERROR :
2311+ case WSA_QOS_ESERVICETYPE :
2312+ case WSA_QOS_EFLOWSPEC :
2313+ case WSA_QOS_EPROVSPECBUF :
2314+ case WSA_QOS_EFILTERSTYLE :
2315+ case WSA_QOS_EFILTERTYPE :
2316+ case WSA_QOS_EFILTERCOUNT :
2317+ case WSA_QOS_EOBJLENGTH :
2318+ case WSA_QOS_EFLOWCOUNT :
2319+ #ifndef _MSC_VER
2320+ case WSA_QOS_EUNKNOWNPSOBJ :
2321+ #endif
2322+ case WSA_QOS_EPOLICYOBJ :
2323+ case WSA_QOS_EFLOWDESC :
2324+ case WSA_QOS_EPSFLOWSPEC :
2325+ case WSA_QOS_EPSFILTERSPEC :
2326+ case WSA_QOS_ESDMODEOBJ :
2327+ case WSA_QOS_ESHAPERATEOBJ :
2328+ case WSA_QOS_RESERVED_PETYPE :
2329+ default : return EIO ;
2330+ }
2331+ }
2332+
2333+ /*
2334+ * On Windows, `errno` is a global macro to a function call.
2335+ * This makes it difficult to debug and single-step our mappings.
2336+ */
2337+ static inline void set_wsa_errno (void )
2338+ {
2339+ DWORD wsa = WSAGetLastError ();
2340+ int e = winsock_error_to_errno (wsa );
2341+ errno = e ;
2342+
2343+ #ifdef DEBUG_WSA_ERRNO
2344+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2345+ fflush (stderr );
2346+ #endif
2347+ }
2348+
2349+ static inline int winsock_return (int ret )
2350+ {
2351+ if (ret < 0 )
2352+ set_wsa_errno ();
2353+
2354+ return ret ;
2355+ }
2356+
2357+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2358+
2359+ #undef strerror
2360+ char * mingw_strerror (int errnum )
2361+ {
2362+ static char buf [41 ] = "" ;
2363+ switch (errnum ) {
2364+ case EWOULDBLOCK :
2365+ xsnprintf (buf , 41 , "%s" , "Operation would block" );
2366+ break ;
2367+ case EINPROGRESS :
2368+ xsnprintf (buf , 41 , "%s" , "Operation now in progress" );
2369+ break ;
2370+ case EALREADY :
2371+ xsnprintf (buf , 41 , "%s" , "Operation already in progress" );
2372+ break ;
2373+ case ENOTSOCK :
2374+ xsnprintf (buf , 41 , "%s" , "Socket operation on non-socket" );
2375+ break ;
2376+ case EDESTADDRREQ :
2377+ xsnprintf (buf , 41 , "%s" , "Destination address required" );
2378+ break ;
2379+ case EMSGSIZE :
2380+ xsnprintf (buf , 41 , "%s" , "Message too long" );
2381+ break ;
2382+ case EPROTOTYPE :
2383+ xsnprintf (buf , 41 , "%s" , "Protocol wrong type for socket" );
2384+ break ;
2385+ case ENOPROTOOPT :
2386+ xsnprintf (buf , 41 , "%s" , "Protocol not available" );
2387+ break ;
2388+ case EPROTONOSUPPORT :
2389+ xsnprintf (buf , 41 , "%s" , "Protocol not supported" );
2390+ break ;
2391+ case EOPNOTSUPP :
2392+ xsnprintf (buf , 41 , "%s" , "Operation not supported" );
2393+ break ;
2394+ case EAFNOSUPPORT :
2395+ xsnprintf (buf , 41 , "%s" , "Address family not supported by protocol" );
2396+ break ;
2397+ case EADDRINUSE :
2398+ xsnprintf (buf , 41 , "%s" , "Address already in use" );
2399+ break ;
2400+ case EADDRNOTAVAIL :
2401+ xsnprintf (buf , 41 , "%s" , "Cannot assign requested address" );
2402+ break ;
2403+ case ENETDOWN :
2404+ xsnprintf (buf , 41 , "%s" , "Network is down" );
2405+ break ;
2406+ case ENETUNREACH :
2407+ xsnprintf (buf , 41 , "%s" , "Network is unreachable" );
2408+ break ;
2409+ case ENETRESET :
2410+ xsnprintf (buf , 41 , "%s" , "Network dropped connection on reset" );
2411+ break ;
2412+ case ECONNABORTED :
2413+ xsnprintf (buf , 41 , "%s" , "Software caused connection abort" );
2414+ break ;
2415+ case ECONNRESET :
2416+ xsnprintf (buf , 41 , "%s" , "Connection reset by peer" );
2417+ break ;
2418+ case ENOBUFS :
2419+ xsnprintf (buf , 41 , "%s" , "No buffer space available" );
2420+ break ;
2421+ case EISCONN :
2422+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is already connected" );
2423+ break ;
2424+ case ENOTCONN :
2425+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is not connected" );
2426+ break ;
2427+ case ETIMEDOUT :
2428+ xsnprintf (buf , 41 , "%s" , "Connection timed out" );
2429+ break ;
2430+ case ECONNREFUSED :
2431+ xsnprintf (buf , 41 , "%s" , "Connection refused" );
2432+ break ;
2433+ case ELOOP :
2434+ xsnprintf (buf , 41 , "%s" , "Too many levels of symbolic links" );
2435+ break ;
2436+ case EHOSTUNREACH :
2437+ xsnprintf (buf , 41 , "%s" , "No route to host" );
2438+ break ;
2439+ default : return strerror (errnum );
2440+ }
2441+ return buf ;
2442+ }
2443+
22342444#undef gethostname
22352445int mingw_gethostname (char * name , int namelen )
22362446{
2237- ensure_socket_initialization ();
2238- return gethostname (name , namelen );
2447+ ensure_socket_initialization ();
2448+ WINSOCK_RETURN ( gethostname (name , namelen ) );
22392449}
22402450
22412451#undef gethostbyname
22422452struct hostent * mingw_gethostbyname (const char * host )
22432453{
2454+ struct hostent * ret ;
2455+
22442456 ensure_socket_initialization ();
2245- return gethostbyname (host );
2457+
2458+ ret = gethostbyname (host );
2459+ if (!ret )
2460+ set_wsa_errno ();
2461+
2462+ return ret ;
22462463}
22472464
22482465#undef getaddrinfo
22492466int mingw_getaddrinfo (const char * node , const char * service ,
22502467 const struct addrinfo * hints , struct addrinfo * * res )
22512468{
22522469 ensure_socket_initialization ();
2253- return getaddrinfo (node , service , hints , res );
2470+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
22542471}
22552472
22562473int mingw_socket (int domain , int type , int protocol )
@@ -2261,16 +2478,7 @@ int mingw_socket(int domain, int type, int protocol)
22612478 ensure_socket_initialization ();
22622479 s = WSASocket (domain , type , protocol , NULL , 0 , 0 );
22632480 if (s == INVALID_SOCKET ) {
2264- /*
2265- * WSAGetLastError() values are regular BSD error codes
2266- * biased by WSABASEERR.
2267- * However, strerror() does not know about networking
2268- * specific errors, which are values beginning at 38 or so.
2269- * Therefore, we choose to leave the biased error code
2270- * in errno so that _if_ someone looks up the code somewhere,
2271- * then it is at least the number that are usually listed.
2272- */
2273- errno = WSAGetLastError ();
2481+ set_wsa_errno ();
22742482 return -1 ;
22752483 }
22762484 /* convert into a file descriptor */
@@ -2286,35 +2494,35 @@ int mingw_socket(int domain, int type, int protocol)
22862494int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
22872495{
22882496 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2289- return connect (s , sa , sz );
2497+ WINSOCK_RETURN ( connect (s , sa , sz ) );
22902498}
22912499
22922500#undef bind
22932501int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
22942502{
22952503 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2296- return bind (s , sa , sz );
2504+ WINSOCK_RETURN ( bind (s , sa , sz ) );
22972505}
22982506
22992507#undef setsockopt
23002508int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
23012509{
23022510 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2303- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2511+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
23042512}
23052513
23062514#undef shutdown
23072515int mingw_shutdown (int sockfd , int how )
23082516{
23092517 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2310- return shutdown (s , how );
2518+ WINSOCK_RETURN ( shutdown (s , how ) );
23112519}
23122520
23132521#undef listen
23142522int mingw_listen (int sockfd , int backlog )
23152523{
23162524 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2317- return listen (s , backlog );
2525+ WINSOCK_RETURN ( listen (s , backlog ) );
23182526}
23192527
23202528#undef accept
@@ -2325,6 +2533,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
23252533 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
23262534 SOCKET s2 = accept (s1 , sa , sz );
23272535
2536+ if (s2 == INVALID_SOCKET ) {
2537+ set_wsa_errno ();
2538+ return -1 ;
2539+ }
2540+
23282541 /* convert into a file descriptor */
23292542 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
23302543 int err = errno ;
0 commit comments