@@ -2021,26 +2021,158 @@ static void ensure_socket_initialization(void)
2021
2021
initialized = 1 ;
2022
2022
}
2023
2023
2024
+ static int winsock_error_to_errno (DWORD err )
2025
+ {
2026
+ switch (err ) {
2027
+ case WSAEINTR : return EINTR ;
2028
+ case WSAEBADF : return EBADF ;
2029
+ case WSAEACCES : return EACCES ;
2030
+ case WSAEFAULT : return EFAULT ;
2031
+ case WSAEINVAL : return EINVAL ;
2032
+ case WSAEMFILE : return EMFILE ;
2033
+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2034
+ case WSAEINPROGRESS : return EINPROGRESS ;
2035
+ case WSAEALREADY : return EALREADY ;
2036
+ case WSAENOTSOCK : return ENOTSOCK ;
2037
+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2038
+ case WSAEMSGSIZE : return EMSGSIZE ;
2039
+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2040
+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2041
+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2042
+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2043
+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2044
+ case WSAEADDRINUSE : return EADDRINUSE ;
2045
+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2046
+ case WSAENETDOWN : return ENETDOWN ;
2047
+ case WSAENETUNREACH : return ENETUNREACH ;
2048
+ case WSAENETRESET : return ENETRESET ;
2049
+ case WSAECONNABORTED : return ECONNABORTED ;
2050
+ case WSAECONNRESET : return ECONNRESET ;
2051
+ case WSAENOBUFS : return ENOBUFS ;
2052
+ case WSAEISCONN : return EISCONN ;
2053
+ case WSAENOTCONN : return ENOTCONN ;
2054
+ case WSAETIMEDOUT : return ETIMEDOUT ;
2055
+ case WSAECONNREFUSED : return ECONNREFUSED ;
2056
+ case WSAELOOP : return ELOOP ;
2057
+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2058
+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2059
+ case WSAENOTEMPTY : return ENOTEMPTY ;
2060
+ /* No errno equivalent; default to EIO */
2061
+ case WSAESOCKTNOSUPPORT :
2062
+ case WSAEPFNOSUPPORT :
2063
+ case WSAESHUTDOWN :
2064
+ case WSAETOOMANYREFS :
2065
+ case WSAEHOSTDOWN :
2066
+ case WSAEPROCLIM :
2067
+ case WSAEUSERS :
2068
+ case WSAEDQUOT :
2069
+ case WSAESTALE :
2070
+ case WSAEREMOTE :
2071
+ case WSASYSNOTREADY :
2072
+ case WSAVERNOTSUPPORTED :
2073
+ case WSANOTINITIALISED :
2074
+ case WSAEDISCON :
2075
+ case WSAENOMORE :
2076
+ case WSAECANCELLED :
2077
+ case WSAEINVALIDPROCTABLE :
2078
+ case WSAEINVALIDPROVIDER :
2079
+ case WSAEPROVIDERFAILEDINIT :
2080
+ case WSASYSCALLFAILURE :
2081
+ case WSASERVICE_NOT_FOUND :
2082
+ case WSATYPE_NOT_FOUND :
2083
+ case WSA_E_NO_MORE :
2084
+ case WSA_E_CANCELLED :
2085
+ case WSAEREFUSED :
2086
+ case WSAHOST_NOT_FOUND :
2087
+ case WSATRY_AGAIN :
2088
+ case WSANO_RECOVERY :
2089
+ case WSANO_DATA :
2090
+ case WSA_QOS_RECEIVERS :
2091
+ case WSA_QOS_SENDERS :
2092
+ case WSA_QOS_NO_SENDERS :
2093
+ case WSA_QOS_NO_RECEIVERS :
2094
+ case WSA_QOS_REQUEST_CONFIRMED :
2095
+ case WSA_QOS_ADMISSION_FAILURE :
2096
+ case WSA_QOS_POLICY_FAILURE :
2097
+ case WSA_QOS_BAD_STYLE :
2098
+ case WSA_QOS_BAD_OBJECT :
2099
+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2100
+ case WSA_QOS_GENERIC_ERROR :
2101
+ case WSA_QOS_ESERVICETYPE :
2102
+ case WSA_QOS_EFLOWSPEC :
2103
+ case WSA_QOS_EPROVSPECBUF :
2104
+ case WSA_QOS_EFILTERSTYLE :
2105
+ case WSA_QOS_EFILTERTYPE :
2106
+ case WSA_QOS_EFILTERCOUNT :
2107
+ case WSA_QOS_EOBJLENGTH :
2108
+ case WSA_QOS_EFLOWCOUNT :
2109
+ #ifndef _MSC_VER
2110
+ case WSA_QOS_EUNKNOWNPSOBJ :
2111
+ #endif
2112
+ case WSA_QOS_EPOLICYOBJ :
2113
+ case WSA_QOS_EFLOWDESC :
2114
+ case WSA_QOS_EPSFLOWSPEC :
2115
+ case WSA_QOS_EPSFILTERSPEC :
2116
+ case WSA_QOS_ESDMODEOBJ :
2117
+ case WSA_QOS_ESHAPERATEOBJ :
2118
+ case WSA_QOS_RESERVED_PETYPE :
2119
+ default : return EIO ;
2120
+ }
2121
+ }
2122
+
2123
+ /*
2124
+ * On Windows, `errno` is a global macro to a function call.
2125
+ * This makes it difficult to debug and single-step our mappings.
2126
+ */
2127
+ static inline void set_wsa_errno (void )
2128
+ {
2129
+ DWORD wsa = WSAGetLastError ();
2130
+ int e = winsock_error_to_errno (wsa );
2131
+ errno = e ;
2132
+
2133
+ #ifdef DEBUG_WSA_ERRNO
2134
+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2135
+ fflush (stderr );
2136
+ #endif
2137
+ }
2138
+
2139
+ static inline int winsock_return (int ret )
2140
+ {
2141
+ if (ret < 0 )
2142
+ set_wsa_errno ();
2143
+
2144
+ return ret ;
2145
+ }
2146
+
2147
+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2148
+
2024
2149
#undef gethostname
2025
2150
int mingw_gethostname (char * name , int namelen )
2026
2151
{
2027
- ensure_socket_initialization ();
2028
- return gethostname (name , namelen );
2152
+ ensure_socket_initialization ();
2153
+ WINSOCK_RETURN ( gethostname (name , namelen ) );
2029
2154
}
2030
2155
2031
2156
#undef gethostbyname
2032
2157
struct hostent * mingw_gethostbyname (const char * host )
2033
2158
{
2159
+ struct hostent * ret ;
2160
+
2034
2161
ensure_socket_initialization ();
2035
- return gethostbyname (host );
2162
+
2163
+ ret = gethostbyname (host );
2164
+ if (!ret )
2165
+ set_wsa_errno ();
2166
+
2167
+ return ret ;
2036
2168
}
2037
2169
2038
2170
#undef getaddrinfo
2039
2171
int mingw_getaddrinfo (const char * node , const char * service ,
2040
2172
const struct addrinfo * hints , struct addrinfo * * res )
2041
2173
{
2042
2174
ensure_socket_initialization ();
2043
- return getaddrinfo (node , service , hints , res );
2175
+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
2044
2176
}
2045
2177
2046
2178
int mingw_socket (int domain , int type , int protocol )
@@ -2060,7 +2192,7 @@ int mingw_socket(int domain, int type, int protocol)
2060
2192
* in errno so that _if_ someone looks up the code somewhere,
2061
2193
* then it is at least the number that are usually listed.
2062
2194
*/
2063
- errno = WSAGetLastError ();
2195
+ set_wsa_errno ();
2064
2196
return -1 ;
2065
2197
}
2066
2198
/* convert into a file descriptor */
@@ -2076,35 +2208,35 @@ int mingw_socket(int domain, int type, int protocol)
2076
2208
int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
2077
2209
{
2078
2210
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2079
- return connect (s , sa , sz );
2211
+ WINSOCK_RETURN ( connect (s , sa , sz ) );
2080
2212
}
2081
2213
2082
2214
#undef bind
2083
2215
int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
2084
2216
{
2085
2217
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2086
- return bind (s , sa , sz );
2218
+ WINSOCK_RETURN ( bind (s , sa , sz ) );
2087
2219
}
2088
2220
2089
2221
#undef setsockopt
2090
2222
int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
2091
2223
{
2092
2224
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2093
- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2225
+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
2094
2226
}
2095
2227
2096
2228
#undef shutdown
2097
2229
int mingw_shutdown (int sockfd , int how )
2098
2230
{
2099
2231
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2100
- return shutdown (s , how );
2232
+ WINSOCK_RETURN ( shutdown (s , how ) );
2101
2233
}
2102
2234
2103
2235
#undef listen
2104
2236
int mingw_listen (int sockfd , int backlog )
2105
2237
{
2106
2238
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2107
- return listen (s , backlog );
2239
+ WINSOCK_RETURN ( listen (s , backlog ) );
2108
2240
}
2109
2241
2110
2242
#undef accept
@@ -2115,6 +2247,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
2115
2247
SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
2116
2248
SOCKET s2 = accept (s1 , sa , sz );
2117
2249
2250
+ if (s2 == INVALID_SOCKET ) {
2251
+ set_wsa_errno ();
2252
+ return -1 ;
2253
+ }
2254
+
2118
2255
/* convert into a file descriptor */
2119
2256
if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
2120
2257
int err = errno ;
0 commit comments