@@ -2519,26 +2519,243 @@ static void ensure_socket_initialization(void)
25192519 initialized = 1 ;
25202520}
25212521
2522+ static int winsock_error_to_errno (DWORD err )
2523+ {
2524+ switch (err ) {
2525+ case WSAEINTR : return EINTR ;
2526+ case WSAEBADF : return EBADF ;
2527+ case WSAEACCES : return EACCES ;
2528+ case WSAEFAULT : return EFAULT ;
2529+ case WSAEINVAL : return EINVAL ;
2530+ case WSAEMFILE : return EMFILE ;
2531+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2532+ case WSAEINPROGRESS : return EINPROGRESS ;
2533+ case WSAEALREADY : return EALREADY ;
2534+ case WSAENOTSOCK : return ENOTSOCK ;
2535+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2536+ case WSAEMSGSIZE : return EMSGSIZE ;
2537+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2538+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2539+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2540+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2541+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2542+ case WSAEADDRINUSE : return EADDRINUSE ;
2543+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2544+ case WSAENETDOWN : return ENETDOWN ;
2545+ case WSAENETUNREACH : return ENETUNREACH ;
2546+ case WSAENETRESET : return ENETRESET ;
2547+ case WSAECONNABORTED : return ECONNABORTED ;
2548+ case WSAECONNRESET : return ECONNRESET ;
2549+ case WSAENOBUFS : return ENOBUFS ;
2550+ case WSAEISCONN : return EISCONN ;
2551+ case WSAENOTCONN : return ENOTCONN ;
2552+ case WSAETIMEDOUT : return ETIMEDOUT ;
2553+ case WSAECONNREFUSED : return ECONNREFUSED ;
2554+ case WSAELOOP : return ELOOP ;
2555+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2556+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2557+ case WSAENOTEMPTY : return ENOTEMPTY ;
2558+ /* No errno equivalent; default to EIO */
2559+ case WSAESOCKTNOSUPPORT :
2560+ case WSAEPFNOSUPPORT :
2561+ case WSAESHUTDOWN :
2562+ case WSAETOOMANYREFS :
2563+ case WSAEHOSTDOWN :
2564+ case WSAEPROCLIM :
2565+ case WSAEUSERS :
2566+ case WSAEDQUOT :
2567+ case WSAESTALE :
2568+ case WSAEREMOTE :
2569+ case WSASYSNOTREADY :
2570+ case WSAVERNOTSUPPORTED :
2571+ case WSANOTINITIALISED :
2572+ case WSAEDISCON :
2573+ case WSAENOMORE :
2574+ case WSAECANCELLED :
2575+ case WSAEINVALIDPROCTABLE :
2576+ case WSAEINVALIDPROVIDER :
2577+ case WSAEPROVIDERFAILEDINIT :
2578+ case WSASYSCALLFAILURE :
2579+ case WSASERVICE_NOT_FOUND :
2580+ case WSATYPE_NOT_FOUND :
2581+ case WSA_E_NO_MORE :
2582+ case WSA_E_CANCELLED :
2583+ case WSAEREFUSED :
2584+ case WSAHOST_NOT_FOUND :
2585+ case WSATRY_AGAIN :
2586+ case WSANO_RECOVERY :
2587+ case WSANO_DATA :
2588+ case WSA_QOS_RECEIVERS :
2589+ case WSA_QOS_SENDERS :
2590+ case WSA_QOS_NO_SENDERS :
2591+ case WSA_QOS_NO_RECEIVERS :
2592+ case WSA_QOS_REQUEST_CONFIRMED :
2593+ case WSA_QOS_ADMISSION_FAILURE :
2594+ case WSA_QOS_POLICY_FAILURE :
2595+ case WSA_QOS_BAD_STYLE :
2596+ case WSA_QOS_BAD_OBJECT :
2597+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2598+ case WSA_QOS_GENERIC_ERROR :
2599+ case WSA_QOS_ESERVICETYPE :
2600+ case WSA_QOS_EFLOWSPEC :
2601+ case WSA_QOS_EPROVSPECBUF :
2602+ case WSA_QOS_EFILTERSTYLE :
2603+ case WSA_QOS_EFILTERTYPE :
2604+ case WSA_QOS_EFILTERCOUNT :
2605+ case WSA_QOS_EOBJLENGTH :
2606+ case WSA_QOS_EFLOWCOUNT :
2607+ #ifndef _MSC_VER
2608+ case WSA_QOS_EUNKNOWNPSOBJ :
2609+ #endif
2610+ case WSA_QOS_EPOLICYOBJ :
2611+ case WSA_QOS_EFLOWDESC :
2612+ case WSA_QOS_EPSFLOWSPEC :
2613+ case WSA_QOS_EPSFILTERSPEC :
2614+ case WSA_QOS_ESDMODEOBJ :
2615+ case WSA_QOS_ESHAPERATEOBJ :
2616+ case WSA_QOS_RESERVED_PETYPE :
2617+ default : return EIO ;
2618+ }
2619+ }
2620+
2621+ /*
2622+ * On Windows, `errno` is a global macro to a function call.
2623+ * This makes it difficult to debug and single-step our mappings.
2624+ */
2625+ static inline void set_wsa_errno (void )
2626+ {
2627+ DWORD wsa = WSAGetLastError ();
2628+ int e = winsock_error_to_errno (wsa );
2629+ errno = e ;
2630+
2631+ #ifdef DEBUG_WSA_ERRNO
2632+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2633+ fflush (stderr );
2634+ #endif
2635+ }
2636+
2637+ static inline int winsock_return (int ret )
2638+ {
2639+ if (ret < 0 )
2640+ set_wsa_errno ();
2641+
2642+ return ret ;
2643+ }
2644+
2645+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2646+
2647+ #undef strerror
2648+ char * mingw_strerror (int errnum )
2649+ {
2650+ static char buf [41 ] = "" ;
2651+ switch (errnum ) {
2652+ case EWOULDBLOCK :
2653+ xsnprintf (buf , 41 , "%s" , "Operation would block" );
2654+ break ;
2655+ case EINPROGRESS :
2656+ xsnprintf (buf , 41 , "%s" , "Operation now in progress" );
2657+ break ;
2658+ case EALREADY :
2659+ xsnprintf (buf , 41 , "%s" , "Operation already in progress" );
2660+ break ;
2661+ case ENOTSOCK :
2662+ xsnprintf (buf , 41 , "%s" , "Socket operation on non-socket" );
2663+ break ;
2664+ case EDESTADDRREQ :
2665+ xsnprintf (buf , 41 , "%s" , "Destination address required" );
2666+ break ;
2667+ case EMSGSIZE :
2668+ xsnprintf (buf , 41 , "%s" , "Message too long" );
2669+ break ;
2670+ case EPROTOTYPE :
2671+ xsnprintf (buf , 41 , "%s" , "Protocol wrong type for socket" );
2672+ break ;
2673+ case ENOPROTOOPT :
2674+ xsnprintf (buf , 41 , "%s" , "Protocol not available" );
2675+ break ;
2676+ case EPROTONOSUPPORT :
2677+ xsnprintf (buf , 41 , "%s" , "Protocol not supported" );
2678+ break ;
2679+ case EOPNOTSUPP :
2680+ xsnprintf (buf , 41 , "%s" , "Operation not supported" );
2681+ break ;
2682+ case EAFNOSUPPORT :
2683+ xsnprintf (buf , 41 , "%s" , "Address family not supported by protocol" );
2684+ break ;
2685+ case EADDRINUSE :
2686+ xsnprintf (buf , 41 , "%s" , "Address already in use" );
2687+ break ;
2688+ case EADDRNOTAVAIL :
2689+ xsnprintf (buf , 41 , "%s" , "Cannot assign requested address" );
2690+ break ;
2691+ case ENETDOWN :
2692+ xsnprintf (buf , 41 , "%s" , "Network is down" );
2693+ break ;
2694+ case ENETUNREACH :
2695+ xsnprintf (buf , 41 , "%s" , "Network is unreachable" );
2696+ break ;
2697+ case ENETRESET :
2698+ xsnprintf (buf , 41 , "%s" , "Network dropped connection on reset" );
2699+ break ;
2700+ case ECONNABORTED :
2701+ xsnprintf (buf , 41 , "%s" , "Software caused connection abort" );
2702+ break ;
2703+ case ECONNRESET :
2704+ xsnprintf (buf , 41 , "%s" , "Connection reset by peer" );
2705+ break ;
2706+ case ENOBUFS :
2707+ xsnprintf (buf , 41 , "%s" , "No buffer space available" );
2708+ break ;
2709+ case EISCONN :
2710+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is already connected" );
2711+ break ;
2712+ case ENOTCONN :
2713+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is not connected" );
2714+ break ;
2715+ case ETIMEDOUT :
2716+ xsnprintf (buf , 41 , "%s" , "Connection timed out" );
2717+ break ;
2718+ case ECONNREFUSED :
2719+ xsnprintf (buf , 41 , "%s" , "Connection refused" );
2720+ break ;
2721+ case ELOOP :
2722+ xsnprintf (buf , 41 , "%s" , "Too many levels of symbolic links" );
2723+ break ;
2724+ case EHOSTUNREACH :
2725+ xsnprintf (buf , 41 , "%s" , "No route to host" );
2726+ break ;
2727+ default : return strerror (errnum );
2728+ }
2729+ return buf ;
2730+ }
2731+
25222732#undef gethostname
25232733int mingw_gethostname (char * name , int namelen )
25242734{
2525- ensure_socket_initialization ();
2526- return gethostname (name , namelen );
2735+ ensure_socket_initialization ();
2736+ WINSOCK_RETURN ( gethostname (name , namelen ) );
25272737}
25282738
25292739#undef gethostbyname
25302740struct hostent * mingw_gethostbyname (const char * host )
25312741{
2742+ struct hostent * ret ;
2743+
25322744 ensure_socket_initialization ();
2533- return gethostbyname (host );
2745+
2746+ ret = gethostbyname (host );
2747+ if (!ret )
2748+ set_wsa_errno ();
2749+
2750+ return ret ;
25342751}
25352752
25362753#undef getaddrinfo
25372754int mingw_getaddrinfo (const char * node , const char * service ,
25382755 const struct addrinfo * hints , struct addrinfo * * res )
25392756{
25402757 ensure_socket_initialization ();
2541- return getaddrinfo (node , service , hints , res );
2758+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
25422759}
25432760
25442761int mingw_socket (int domain , int type , int protocol )
@@ -2549,16 +2766,7 @@ int mingw_socket(int domain, int type, int protocol)
25492766 ensure_socket_initialization ();
25502767 s = WSASocket (domain , type , protocol , NULL , 0 , 0 );
25512768 if (s == INVALID_SOCKET ) {
2552- /*
2553- * WSAGetLastError() values are regular BSD error codes
2554- * biased by WSABASEERR.
2555- * However, strerror() does not know about networking
2556- * specific errors, which are values beginning at 38 or so.
2557- * Therefore, we choose to leave the biased error code
2558- * in errno so that _if_ someone looks up the code somewhere,
2559- * then it is at least the number that are usually listed.
2560- */
2561- errno = WSAGetLastError ();
2769+ set_wsa_errno ();
25622770 return -1 ;
25632771 }
25642772 /* convert into a file descriptor */
@@ -2574,35 +2782,35 @@ int mingw_socket(int domain, int type, int protocol)
25742782int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
25752783{
25762784 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2577- return connect (s , sa , sz );
2785+ WINSOCK_RETURN ( connect (s , sa , sz ) );
25782786}
25792787
25802788#undef bind
25812789int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
25822790{
25832791 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2584- return bind (s , sa , sz );
2792+ WINSOCK_RETURN ( bind (s , sa , sz ) );
25852793}
25862794
25872795#undef setsockopt
25882796int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
25892797{
25902798 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2591- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2799+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
25922800}
25932801
25942802#undef shutdown
25952803int mingw_shutdown (int sockfd , int how )
25962804{
25972805 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2598- return shutdown (s , how );
2806+ WINSOCK_RETURN ( shutdown (s , how ) );
25992807}
26002808
26012809#undef listen
26022810int mingw_listen (int sockfd , int backlog )
26032811{
26042812 SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2605- return listen (s , backlog );
2813+ WINSOCK_RETURN ( listen (s , backlog ) );
26062814}
26072815
26082816#undef accept
@@ -2613,6 +2821,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
26132821 SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
26142822 SOCKET s2 = accept (s1 , sa , sz );
26152823
2824+ if (s2 == INVALID_SOCKET ) {
2825+ set_wsa_errno ();
2826+ return -1 ;
2827+ }
2828+
26162829 /* convert into a file descriptor */
26172830 if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
26182831 int err = errno ;
0 commit comments