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