@@ -2089,26 +2089,158 @@ static void ensure_socket_initialization(void)
2089
2089
initialized = 1 ;
2090
2090
}
2091
2091
2092
+ static int winsock_error_to_errno (DWORD err )
2093
+ {
2094
+ switch (err ) {
2095
+ case WSAEINTR : return EINTR ;
2096
+ case WSAEBADF : return EBADF ;
2097
+ case WSAEACCES : return EACCES ;
2098
+ case WSAEFAULT : return EFAULT ;
2099
+ case WSAEINVAL : return EINVAL ;
2100
+ case WSAEMFILE : return EMFILE ;
2101
+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2102
+ case WSAEINPROGRESS : return EINPROGRESS ;
2103
+ case WSAEALREADY : return EALREADY ;
2104
+ case WSAENOTSOCK : return ENOTSOCK ;
2105
+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2106
+ case WSAEMSGSIZE : return EMSGSIZE ;
2107
+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2108
+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2109
+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2110
+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2111
+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2112
+ case WSAEADDRINUSE : return EADDRINUSE ;
2113
+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2114
+ case WSAENETDOWN : return ENETDOWN ;
2115
+ case WSAENETUNREACH : return ENETUNREACH ;
2116
+ case WSAENETRESET : return ENETRESET ;
2117
+ case WSAECONNABORTED : return ECONNABORTED ;
2118
+ case WSAECONNRESET : return ECONNRESET ;
2119
+ case WSAENOBUFS : return ENOBUFS ;
2120
+ case WSAEISCONN : return EISCONN ;
2121
+ case WSAENOTCONN : return ENOTCONN ;
2122
+ case WSAETIMEDOUT : return ETIMEDOUT ;
2123
+ case WSAECONNREFUSED : return ECONNREFUSED ;
2124
+ case WSAELOOP : return ELOOP ;
2125
+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2126
+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2127
+ case WSAENOTEMPTY : return ENOTEMPTY ;
2128
+ /* No errno equivalent; default to EIO */
2129
+ case WSAESOCKTNOSUPPORT :
2130
+ case WSAEPFNOSUPPORT :
2131
+ case WSAESHUTDOWN :
2132
+ case WSAETOOMANYREFS :
2133
+ case WSAEHOSTDOWN :
2134
+ case WSAEPROCLIM :
2135
+ case WSAEUSERS :
2136
+ case WSAEDQUOT :
2137
+ case WSAESTALE :
2138
+ case WSAEREMOTE :
2139
+ case WSASYSNOTREADY :
2140
+ case WSAVERNOTSUPPORTED :
2141
+ case WSANOTINITIALISED :
2142
+ case WSAEDISCON :
2143
+ case WSAENOMORE :
2144
+ case WSAECANCELLED :
2145
+ case WSAEINVALIDPROCTABLE :
2146
+ case WSAEINVALIDPROVIDER :
2147
+ case WSAEPROVIDERFAILEDINIT :
2148
+ case WSASYSCALLFAILURE :
2149
+ case WSASERVICE_NOT_FOUND :
2150
+ case WSATYPE_NOT_FOUND :
2151
+ case WSA_E_NO_MORE :
2152
+ case WSA_E_CANCELLED :
2153
+ case WSAEREFUSED :
2154
+ case WSAHOST_NOT_FOUND :
2155
+ case WSATRY_AGAIN :
2156
+ case WSANO_RECOVERY :
2157
+ case WSANO_DATA :
2158
+ case WSA_QOS_RECEIVERS :
2159
+ case WSA_QOS_SENDERS :
2160
+ case WSA_QOS_NO_SENDERS :
2161
+ case WSA_QOS_NO_RECEIVERS :
2162
+ case WSA_QOS_REQUEST_CONFIRMED :
2163
+ case WSA_QOS_ADMISSION_FAILURE :
2164
+ case WSA_QOS_POLICY_FAILURE :
2165
+ case WSA_QOS_BAD_STYLE :
2166
+ case WSA_QOS_BAD_OBJECT :
2167
+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2168
+ case WSA_QOS_GENERIC_ERROR :
2169
+ case WSA_QOS_ESERVICETYPE :
2170
+ case WSA_QOS_EFLOWSPEC :
2171
+ case WSA_QOS_EPROVSPECBUF :
2172
+ case WSA_QOS_EFILTERSTYLE :
2173
+ case WSA_QOS_EFILTERTYPE :
2174
+ case WSA_QOS_EFILTERCOUNT :
2175
+ case WSA_QOS_EOBJLENGTH :
2176
+ case WSA_QOS_EFLOWCOUNT :
2177
+ #ifndef _MSC_VER
2178
+ case WSA_QOS_EUNKNOWNPSOBJ :
2179
+ #endif
2180
+ case WSA_QOS_EPOLICYOBJ :
2181
+ case WSA_QOS_EFLOWDESC :
2182
+ case WSA_QOS_EPSFLOWSPEC :
2183
+ case WSA_QOS_EPSFILTERSPEC :
2184
+ case WSA_QOS_ESDMODEOBJ :
2185
+ case WSA_QOS_ESHAPERATEOBJ :
2186
+ case WSA_QOS_RESERVED_PETYPE :
2187
+ default : return EIO ;
2188
+ }
2189
+ }
2190
+
2191
+ /*
2192
+ * On Windows, `errno` is a global macro to a function call.
2193
+ * This makes it difficult to debug and single-step our mappings.
2194
+ */
2195
+ static inline void set_wsa_errno (void )
2196
+ {
2197
+ DWORD wsa = WSAGetLastError ();
2198
+ int e = winsock_error_to_errno (wsa );
2199
+ errno = e ;
2200
+
2201
+ #ifdef DEBUG_WSA_ERRNO
2202
+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2203
+ fflush (stderr );
2204
+ #endif
2205
+ }
2206
+
2207
+ static inline int winsock_return (int ret )
2208
+ {
2209
+ if (ret < 0 )
2210
+ set_wsa_errno ();
2211
+
2212
+ return ret ;
2213
+ }
2214
+
2215
+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2216
+
2092
2217
#undef gethostname
2093
2218
int mingw_gethostname (char * name , int namelen )
2094
2219
{
2095
- ensure_socket_initialization ();
2096
- return gethostname (name , namelen );
2220
+ ensure_socket_initialization ();
2221
+ WINSOCK_RETURN ( gethostname (name , namelen ) );
2097
2222
}
2098
2223
2099
2224
#undef gethostbyname
2100
2225
struct hostent * mingw_gethostbyname (const char * host )
2101
2226
{
2227
+ struct hostent * ret ;
2228
+
2102
2229
ensure_socket_initialization ();
2103
- return gethostbyname (host );
2230
+
2231
+ ret = gethostbyname (host );
2232
+ if (!ret )
2233
+ set_wsa_errno ();
2234
+
2235
+ return ret ;
2104
2236
}
2105
2237
2106
2238
#undef getaddrinfo
2107
2239
int mingw_getaddrinfo (const char * node , const char * service ,
2108
2240
const struct addrinfo * hints , struct addrinfo * * res )
2109
2241
{
2110
2242
ensure_socket_initialization ();
2111
- return getaddrinfo (node , service , hints , res );
2243
+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
2112
2244
}
2113
2245
2114
2246
int mingw_socket (int domain , int type , int protocol )
@@ -2128,7 +2260,7 @@ int mingw_socket(int domain, int type, int protocol)
2128
2260
* in errno so that _if_ someone looks up the code somewhere,
2129
2261
* then it is at least the number that are usually listed.
2130
2262
*/
2131
- errno = WSAGetLastError ();
2263
+ set_wsa_errno ();
2132
2264
return -1 ;
2133
2265
}
2134
2266
/* convert into a file descriptor */
@@ -2144,35 +2276,35 @@ int mingw_socket(int domain, int type, int protocol)
2144
2276
int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
2145
2277
{
2146
2278
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2147
- return connect (s , sa , sz );
2279
+ WINSOCK_RETURN ( connect (s , sa , sz ) );
2148
2280
}
2149
2281
2150
2282
#undef bind
2151
2283
int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
2152
2284
{
2153
2285
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2154
- return bind (s , sa , sz );
2286
+ WINSOCK_RETURN ( bind (s , sa , sz ) );
2155
2287
}
2156
2288
2157
2289
#undef setsockopt
2158
2290
int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
2159
2291
{
2160
2292
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2161
- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2293
+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
2162
2294
}
2163
2295
2164
2296
#undef shutdown
2165
2297
int mingw_shutdown (int sockfd , int how )
2166
2298
{
2167
2299
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2168
- return shutdown (s , how );
2300
+ WINSOCK_RETURN ( shutdown (s , how ) );
2169
2301
}
2170
2302
2171
2303
#undef listen
2172
2304
int mingw_listen (int sockfd , int backlog )
2173
2305
{
2174
2306
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2175
- return listen (s , backlog );
2307
+ WINSOCK_RETURN ( listen (s , backlog ) );
2176
2308
}
2177
2309
2178
2310
#undef accept
@@ -2183,6 +2315,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
2183
2315
SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
2184
2316
SOCKET s2 = accept (s1 , sa , sz );
2185
2317
2318
+ if (s2 == INVALID_SOCKET ) {
2319
+ set_wsa_errno ();
2320
+ return -1 ;
2321
+ }
2322
+
2186
2323
/* convert into a file descriptor */
2187
2324
if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
2188
2325
int err = errno ;
0 commit comments