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