@@ -2453,26 +2453,243 @@ static void ensure_socket_initialization(void)
24532453 initialized = 1 ;
24542454}
24552455
2456+ static int winsock_error_to_errno (DWORD err )
2457+ {
2458+ switch (err ) {
2459+ case WSAEINTR : return EINTR ;
2460+ case WSAEBADF : return EBADF ;
2461+ case WSAEACCES : return EACCES ;
2462+ case WSAEFAULT : return EFAULT ;
2463+ case WSAEINVAL : return EINVAL ;
2464+ case WSAEMFILE : return EMFILE ;
2465+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2466+ case WSAEINPROGRESS : return EINPROGRESS ;
2467+ case WSAEALREADY : return EALREADY ;
2468+ case WSAENOTSOCK : return ENOTSOCK ;
2469+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2470+ case WSAEMSGSIZE : return EMSGSIZE ;
2471+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2472+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2473+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2474+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2475+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2476+ case WSAEADDRINUSE : return EADDRINUSE ;
2477+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2478+ case WSAENETDOWN : return ENETDOWN ;
2479+ case WSAENETUNREACH : return ENETUNREACH ;
2480+ case WSAENETRESET : return ENETRESET ;
2481+ case WSAECONNABORTED : return ECONNABORTED ;
2482+ case WSAECONNRESET : return ECONNRESET ;
2483+ case WSAENOBUFS : return ENOBUFS ;
2484+ case WSAEISCONN : return EISCONN ;
2485+ case WSAENOTCONN : return ENOTCONN ;
2486+ case WSAETIMEDOUT : return ETIMEDOUT ;
2487+ case WSAECONNREFUSED : return ECONNREFUSED ;
2488+ case WSAELOOP : return ELOOP ;
2489+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2490+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2491+ case WSAENOTEMPTY : return ENOTEMPTY ;
2492+ /* No errno equivalent; default to EIO */
2493+ case WSAESOCKTNOSUPPORT :
2494+ case WSAEPFNOSUPPORT :
2495+ case WSAESHUTDOWN :
2496+ case WSAETOOMANYREFS :
2497+ case WSAEHOSTDOWN :
2498+ case WSAEPROCLIM :
2499+ case WSAEUSERS :
2500+ case WSAEDQUOT :
2501+ case WSAESTALE :
2502+ case WSAEREMOTE :
2503+ case WSASYSNOTREADY :
2504+ case WSAVERNOTSUPPORTED :
2505+ case WSANOTINITIALISED :
2506+ case WSAEDISCON :
2507+ case WSAENOMORE :
2508+ case WSAECANCELLED :
2509+ case WSAEINVALIDPROCTABLE :
2510+ case WSAEINVALIDPROVIDER :
2511+ case WSAEPROVIDERFAILEDINIT :
2512+ case WSASYSCALLFAILURE :
2513+ case WSASERVICE_NOT_FOUND :
2514+ case WSATYPE_NOT_FOUND :
2515+ case WSA_E_NO_MORE :
2516+ case WSA_E_CANCELLED :
2517+ case WSAEREFUSED :
2518+ case WSAHOST_NOT_FOUND :
2519+ case WSATRY_AGAIN :
2520+ case WSANO_RECOVERY :
2521+ case WSANO_DATA :
2522+ case WSA_QOS_RECEIVERS :
2523+ case WSA_QOS_SENDERS :
2524+ case WSA_QOS_NO_SENDERS :
2525+ case WSA_QOS_NO_RECEIVERS :
2526+ case WSA_QOS_REQUEST_CONFIRMED :
2527+ case WSA_QOS_ADMISSION_FAILURE :
2528+ case WSA_QOS_POLICY_FAILURE :
2529+ case WSA_QOS_BAD_STYLE :
2530+ case WSA_QOS_BAD_OBJECT :
2531+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2532+ case WSA_QOS_GENERIC_ERROR :
2533+ case WSA_QOS_ESERVICETYPE :
2534+ case WSA_QOS_EFLOWSPEC :
2535+ case WSA_QOS_EPROVSPECBUF :
2536+ case WSA_QOS_EFILTERSTYLE :
2537+ case WSA_QOS_EFILTERTYPE :
2538+ case WSA_QOS_EFILTERCOUNT :
2539+ case WSA_QOS_EOBJLENGTH :
2540+ case WSA_QOS_EFLOWCOUNT :
2541+ #ifndef _MSC_VER
2542+ case WSA_QOS_EUNKNOWNPSOBJ :
2543+ #endif
2544+ case WSA_QOS_EPOLICYOBJ :
2545+ case WSA_QOS_EFLOWDESC :
2546+ case WSA_QOS_EPSFLOWSPEC :
2547+ case WSA_QOS_EPSFILTERSPEC :
2548+ case WSA_QOS_ESDMODEOBJ :
2549+ case WSA_QOS_ESHAPERATEOBJ :
2550+ case WSA_QOS_RESERVED_PETYPE :
2551+ default : return EIO ;
2552+ }
2553+ }
2554+
2555+ /*
2556+ * On Windows, `errno` is a global macro to a function call.
2557+ * This makes it difficult to debug and single-step our mappings.
2558+ */
2559+ static inline void set_wsa_errno (void )
2560+ {
2561+ DWORD wsa = WSAGetLastError ();
2562+ int e = winsock_error_to_errno (wsa );
2563+ errno = e ;
2564+
2565+ #ifdef DEBUG_WSA_ERRNO
2566+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2567+ fflush (stderr );
2568+ #endif
2569+ }
2570+
2571+ static inline int winsock_return (int ret )
2572+ {
2573+ if (ret < 0 )
2574+ set_wsa_errno ();
2575+
2576+ return ret ;
2577+ }
2578+
2579+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2580+
2581+ #undef strerror
2582+ char * mingw_strerror (int errnum )
2583+ {
2584+ static char buf [41 ] = "" ;
2585+ switch (errnum ) {
2586+ case EWOULDBLOCK :
2587+ xsnprintf (buf , 41 , "%s" , "Operation would block" );
2588+ break ;
2589+ case EINPROGRESS :
2590+ xsnprintf (buf , 41 , "%s" , "Operation now in progress" );
2591+ break ;
2592+ case EALREADY :
2593+ xsnprintf (buf , 41 , "%s" , "Operation already in progress" );
2594+ break ;
2595+ case ENOTSOCK :
2596+ xsnprintf (buf , 41 , "%s" , "Socket operation on non-socket" );
2597+ break ;
2598+ case EDESTADDRREQ :
2599+ xsnprintf (buf , 41 , "%s" , "Destination address required" );
2600+ break ;
2601+ case EMSGSIZE :
2602+ xsnprintf (buf , 41 , "%s" , "Message too long" );
2603+ break ;
2604+ case EPROTOTYPE :
2605+ xsnprintf (buf , 41 , "%s" , "Protocol wrong type for socket" );
2606+ break ;
2607+ case ENOPROTOOPT :
2608+ xsnprintf (buf , 41 , "%s" , "Protocol not available" );
2609+ break ;
2610+ case EPROTONOSUPPORT :
2611+ xsnprintf (buf , 41 , "%s" , "Protocol not supported" );
2612+ break ;
2613+ case EOPNOTSUPP :
2614+ xsnprintf (buf , 41 , "%s" , "Operation not supported" );
2615+ break ;
2616+ case EAFNOSUPPORT :
2617+ xsnprintf (buf , 41 , "%s" , "Address family not supported by protocol" );
2618+ break ;
2619+ case EADDRINUSE :
2620+ xsnprintf (buf , 41 , "%s" , "Address already in use" );
2621+ break ;
2622+ case EADDRNOTAVAIL :
2623+ xsnprintf (buf , 41 , "%s" , "Cannot assign requested address" );
2624+ break ;
2625+ case ENETDOWN :
2626+ xsnprintf (buf , 41 , "%s" , "Network is down" );
2627+ break ;
2628+ case ENETUNREACH :
2629+ xsnprintf (buf , 41 , "%s" , "Network is unreachable" );
2630+ break ;
2631+ case ENETRESET :
2632+ xsnprintf (buf , 41 , "%s" , "Network dropped connection on reset" );
2633+ break ;
2634+ case ECONNABORTED :
2635+ xsnprintf (buf , 41 , "%s" , "Software caused connection abort" );
2636+ break ;
2637+ case ECONNRESET :
2638+ xsnprintf (buf , 41 , "%s" , "Connection reset by peer" );
2639+ break ;
2640+ case ENOBUFS :
2641+ xsnprintf (buf , 41 , "%s" , "No buffer space available" );
2642+ break ;
2643+ case EISCONN :
2644+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is already connected" );
2645+ break ;
2646+ case ENOTCONN :
2647+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is not connected" );
2648+ break ;
2649+ case ETIMEDOUT :
2650+ xsnprintf (buf , 41 , "%s" , "Connection timed out" );
2651+ break ;
2652+ case ECONNREFUSED :
2653+ xsnprintf (buf , 41 , "%s" , "Connection refused" );
2654+ break ;
2655+ case ELOOP :
2656+ xsnprintf (buf , 41 , "%s" , "Too many levels of symbolic links" );
2657+ break ;
2658+ case EHOSTUNREACH :
2659+ xsnprintf (buf , 41 , "%s" , "No route to host" );
2660+ break ;
2661+ default : return strerror (errnum );
2662+ }
2663+ return buf ;
2664+ }
2665+
24562666#undef gethostname
24572667int mingw_gethostname (char * name , int namelen )
24582668{
2459- ensure_socket_initialization ();
2460- return gethostname (name , namelen );
2669+ ensure_socket_initialization ();
2670+ WINSOCK_RETURN ( gethostname (name , namelen ) );
24612671}
24622672
24632673#undef gethostbyname
24642674struct hostent * mingw_gethostbyname (const char * host )
24652675{
2676+ struct hostent * ret ;
2677+
24662678 ensure_socket_initialization ();
2467- return gethostbyname (host );
2679+
2680+ ret = gethostbyname (host );
2681+ if (!ret )
2682+ set_wsa_errno ();
2683+
2684+ return ret ;
24682685}
24692686
24702687#undef getaddrinfo
24712688int mingw_getaddrinfo (const char * node , const char * service ,
24722689 const struct addrinfo * hints , struct addrinfo * * res )
24732690{
24742691 ensure_socket_initialization ();
2475- return getaddrinfo (node , service , hints , res );
2692+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
24762693}
24772694
24782695int mingw_socket (int domain , int type , int protocol )
@@ -2483,16 +2700,7 @@ int mingw_socket(int domain, int type, int protocol)
24832700 ensure_socket_initialization ();
24842701 s = WSASocket (domain , type , protocol , NULL , 0 , 0 );
24852702 if (s == INVALID_SOCKET ) {
2486- /*
2487- * WSAGetLastError() values are regular BSD error codes
2488- * biased by WSABASEERR.
2489- * However, strerror() does not know about networking
2490- * specific errors, which are values beginning at 38 or so.
2491- * Therefore, we choose to leave the biased error code
2492- * in errno so that _if_ someone looks up the code somewhere,
2493- * then it is at least the number that are usually listed.
2494- */
2495- errno = WSAGetLastError ();
2703+ set_wsa_errno ();
24962704 return -1 ;
24972705 }
24982706 /* convert into a file descriptor */
@@ -2508,35 +2716,35 @@ int mingw_socket(int domain, int type, int protocol)
25082716int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
25092717{
25102718 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2511- return connect (s , sa , sz );
2719+ WINSOCK_RETURN ( connect (s , sa , sz ) );
25122720}
25132721
25142722#undef bind
25152723int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
25162724{
25172725 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2518- return bind (s , sa , sz );
2726+ WINSOCK_RETURN ( bind (s , sa , sz ) );
25192727}
25202728
25212729#undef setsockopt
25222730int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
25232731{
25242732 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2525- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2733+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
25262734}
25272735
25282736#undef shutdown
25292737int mingw_shutdown (int sockfd , int how )
25302738{
25312739 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2532- return shutdown (s , how );
2740+ WINSOCK_RETURN ( shutdown (s , how ) );
25332741}
25342742
25352743#undef listen
25362744int mingw_listen (int sockfd , int backlog )
25372745{
25382746 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2539- return listen (s , backlog );
2747+ WINSOCK_RETURN ( listen (s , backlog ) );
25402748}
25412749
25422750#undef accept
@@ -2547,6 +2755,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
25472755 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
25482756 SOCKET s2 = accept (s1 , sa , sz );
25492757
2758+ if (s2 == INVALID_SOCKET ) {
2759+ set_wsa_errno ();
2760+ return -1 ;
2761+ }
2762+
25502763 /* convert into a file descriptor */
25512764 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
25522765 int err = errno ;
0 commit comments