@@ -2191,26 +2191,158 @@ static void ensure_socket_initialization(void)
2191
2191
initialized = 1 ;
2192
2192
}
2193
2193
2194
+ static int winsock_error_to_errno (DWORD err )
2195
+ {
2196
+ switch (err ) {
2197
+ case WSAEINTR : return EINTR ;
2198
+ case WSAEBADF : return EBADF ;
2199
+ case WSAEACCES : return EACCES ;
2200
+ case WSAEFAULT : return EFAULT ;
2201
+ case WSAEINVAL : return EINVAL ;
2202
+ case WSAEMFILE : return EMFILE ;
2203
+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2204
+ case WSAEINPROGRESS : return EINPROGRESS ;
2205
+ case WSAEALREADY : return EALREADY ;
2206
+ case WSAENOTSOCK : return ENOTSOCK ;
2207
+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2208
+ case WSAEMSGSIZE : return EMSGSIZE ;
2209
+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2210
+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2211
+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2212
+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2213
+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2214
+ case WSAEADDRINUSE : return EADDRINUSE ;
2215
+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2216
+ case WSAENETDOWN : return ENETDOWN ;
2217
+ case WSAENETUNREACH : return ENETUNREACH ;
2218
+ case WSAENETRESET : return ENETRESET ;
2219
+ case WSAECONNABORTED : return ECONNABORTED ;
2220
+ case WSAECONNRESET : return ECONNRESET ;
2221
+ case WSAENOBUFS : return ENOBUFS ;
2222
+ case WSAEISCONN : return EISCONN ;
2223
+ case WSAENOTCONN : return ENOTCONN ;
2224
+ case WSAETIMEDOUT : return ETIMEDOUT ;
2225
+ case WSAECONNREFUSED : return ECONNREFUSED ;
2226
+ case WSAELOOP : return ELOOP ;
2227
+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2228
+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2229
+ case WSAENOTEMPTY : return ENOTEMPTY ;
2230
+ /* No errno equivalent; default to EIO */
2231
+ case WSAESOCKTNOSUPPORT :
2232
+ case WSAEPFNOSUPPORT :
2233
+ case WSAESHUTDOWN :
2234
+ case WSAETOOMANYREFS :
2235
+ case WSAEHOSTDOWN :
2236
+ case WSAEPROCLIM :
2237
+ case WSAEUSERS :
2238
+ case WSAEDQUOT :
2239
+ case WSAESTALE :
2240
+ case WSAEREMOTE :
2241
+ case WSASYSNOTREADY :
2242
+ case WSAVERNOTSUPPORTED :
2243
+ case WSANOTINITIALISED :
2244
+ case WSAEDISCON :
2245
+ case WSAENOMORE :
2246
+ case WSAECANCELLED :
2247
+ case WSAEINVALIDPROCTABLE :
2248
+ case WSAEINVALIDPROVIDER :
2249
+ case WSAEPROVIDERFAILEDINIT :
2250
+ case WSASYSCALLFAILURE :
2251
+ case WSASERVICE_NOT_FOUND :
2252
+ case WSATYPE_NOT_FOUND :
2253
+ case WSA_E_NO_MORE :
2254
+ case WSA_E_CANCELLED :
2255
+ case WSAEREFUSED :
2256
+ case WSAHOST_NOT_FOUND :
2257
+ case WSATRY_AGAIN :
2258
+ case WSANO_RECOVERY :
2259
+ case WSANO_DATA :
2260
+ case WSA_QOS_RECEIVERS :
2261
+ case WSA_QOS_SENDERS :
2262
+ case WSA_QOS_NO_SENDERS :
2263
+ case WSA_QOS_NO_RECEIVERS :
2264
+ case WSA_QOS_REQUEST_CONFIRMED :
2265
+ case WSA_QOS_ADMISSION_FAILURE :
2266
+ case WSA_QOS_POLICY_FAILURE :
2267
+ case WSA_QOS_BAD_STYLE :
2268
+ case WSA_QOS_BAD_OBJECT :
2269
+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2270
+ case WSA_QOS_GENERIC_ERROR :
2271
+ case WSA_QOS_ESERVICETYPE :
2272
+ case WSA_QOS_EFLOWSPEC :
2273
+ case WSA_QOS_EPROVSPECBUF :
2274
+ case WSA_QOS_EFILTERSTYLE :
2275
+ case WSA_QOS_EFILTERTYPE :
2276
+ case WSA_QOS_EFILTERCOUNT :
2277
+ case WSA_QOS_EOBJLENGTH :
2278
+ case WSA_QOS_EFLOWCOUNT :
2279
+ #ifndef _MSC_VER
2280
+ case WSA_QOS_EUNKNOWNPSOBJ :
2281
+ #endif
2282
+ case WSA_QOS_EPOLICYOBJ :
2283
+ case WSA_QOS_EFLOWDESC :
2284
+ case WSA_QOS_EPSFLOWSPEC :
2285
+ case WSA_QOS_EPSFILTERSPEC :
2286
+ case WSA_QOS_ESDMODEOBJ :
2287
+ case WSA_QOS_ESHAPERATEOBJ :
2288
+ case WSA_QOS_RESERVED_PETYPE :
2289
+ default : return EIO ;
2290
+ }
2291
+ }
2292
+
2293
+ /*
2294
+ * On Windows, `errno` is a global macro to a function call.
2295
+ * This makes it difficult to debug and single-step our mappings.
2296
+ */
2297
+ static inline void set_wsa_errno (void )
2298
+ {
2299
+ DWORD wsa = WSAGetLastError ();
2300
+ int e = winsock_error_to_errno (wsa );
2301
+ errno = e ;
2302
+
2303
+ #ifdef DEBUG_WSA_ERRNO
2304
+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2305
+ fflush (stderr );
2306
+ #endif
2307
+ }
2308
+
2309
+ static inline int winsock_return (int ret )
2310
+ {
2311
+ if (ret < 0 )
2312
+ set_wsa_errno ();
2313
+
2314
+ return ret ;
2315
+ }
2316
+
2317
+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2318
+
2194
2319
#undef gethostname
2195
2320
int mingw_gethostname (char * name , int namelen )
2196
2321
{
2197
- ensure_socket_initialization ();
2198
- return gethostname (name , namelen );
2322
+ ensure_socket_initialization ();
2323
+ WINSOCK_RETURN ( gethostname (name , namelen ) );
2199
2324
}
2200
2325
2201
2326
#undef gethostbyname
2202
2327
struct hostent * mingw_gethostbyname (const char * host )
2203
2328
{
2329
+ struct hostent * ret ;
2330
+
2204
2331
ensure_socket_initialization ();
2205
- return gethostbyname (host );
2332
+
2333
+ ret = gethostbyname (host );
2334
+ if (!ret )
2335
+ set_wsa_errno ();
2336
+
2337
+ return ret ;
2206
2338
}
2207
2339
2208
2340
#undef getaddrinfo
2209
2341
int mingw_getaddrinfo (const char * node , const char * service ,
2210
2342
const struct addrinfo * hints , struct addrinfo * * res )
2211
2343
{
2212
2344
ensure_socket_initialization ();
2213
- return getaddrinfo (node , service , hints , res );
2345
+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
2214
2346
}
2215
2347
2216
2348
int mingw_socket (int domain , int type , int protocol )
@@ -2230,7 +2362,7 @@ int mingw_socket(int domain, int type, int protocol)
2230
2362
* in errno so that _if_ someone looks up the code somewhere,
2231
2363
* then it is at least the number that are usually listed.
2232
2364
*/
2233
- errno = WSAGetLastError ();
2365
+ set_wsa_errno ();
2234
2366
return -1 ;
2235
2367
}
2236
2368
/* convert into a file descriptor */
@@ -2246,35 +2378,35 @@ int mingw_socket(int domain, int type, int protocol)
2246
2378
int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
2247
2379
{
2248
2380
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2249
- return connect (s , sa , sz );
2381
+ WINSOCK_RETURN ( connect (s , sa , sz ) );
2250
2382
}
2251
2383
2252
2384
#undef bind
2253
2385
int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
2254
2386
{
2255
2387
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2256
- return bind (s , sa , sz );
2388
+ WINSOCK_RETURN ( bind (s , sa , sz ) );
2257
2389
}
2258
2390
2259
2391
#undef setsockopt
2260
2392
int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
2261
2393
{
2262
2394
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2263
- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2395
+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
2264
2396
}
2265
2397
2266
2398
#undef shutdown
2267
2399
int mingw_shutdown (int sockfd , int how )
2268
2400
{
2269
2401
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2270
- return shutdown (s , how );
2402
+ WINSOCK_RETURN ( shutdown (s , how ) );
2271
2403
}
2272
2404
2273
2405
#undef listen
2274
2406
int mingw_listen (int sockfd , int backlog )
2275
2407
{
2276
2408
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2277
- return listen (s , backlog );
2409
+ WINSOCK_RETURN ( listen (s , backlog ) );
2278
2410
}
2279
2411
2280
2412
#undef accept
@@ -2285,6 +2417,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
2285
2417
SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
2286
2418
SOCKET s2 = accept (s1 , sa , sz );
2287
2419
2420
+ if (s2 == INVALID_SOCKET ) {
2421
+ set_wsa_errno ();
2422
+ return -1 ;
2423
+ }
2424
+
2288
2425
/* convert into a file descriptor */
2289
2426
if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
2290
2427
int err = errno ;
0 commit comments