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