@@ -2231,26 +2231,243 @@ static void ensure_socket_initialization(void)
2231
2231
initialized = 1 ;
2232
2232
}
2233
2233
2234
+ static int winsock_error_to_errno (DWORD err )
2235
+ {
2236
+ switch (err ) {
2237
+ case WSAEINTR : return EINTR ;
2238
+ case WSAEBADF : return EBADF ;
2239
+ case WSAEACCES : return EACCES ;
2240
+ case WSAEFAULT : return EFAULT ;
2241
+ case WSAEINVAL : return EINVAL ;
2242
+ case WSAEMFILE : return EMFILE ;
2243
+ case WSAEWOULDBLOCK : return EWOULDBLOCK ;
2244
+ case WSAEINPROGRESS : return EINPROGRESS ;
2245
+ case WSAEALREADY : return EALREADY ;
2246
+ case WSAENOTSOCK : return ENOTSOCK ;
2247
+ case WSAEDESTADDRREQ : return EDESTADDRREQ ;
2248
+ case WSAEMSGSIZE : return EMSGSIZE ;
2249
+ case WSAEPROTOTYPE : return EPROTOTYPE ;
2250
+ case WSAENOPROTOOPT : return ENOPROTOOPT ;
2251
+ case WSAEPROTONOSUPPORT : return EPROTONOSUPPORT ;
2252
+ case WSAEOPNOTSUPP : return EOPNOTSUPP ;
2253
+ case WSAEAFNOSUPPORT : return EAFNOSUPPORT ;
2254
+ case WSAEADDRINUSE : return EADDRINUSE ;
2255
+ case WSAEADDRNOTAVAIL : return EADDRNOTAVAIL ;
2256
+ case WSAENETDOWN : return ENETDOWN ;
2257
+ case WSAENETUNREACH : return ENETUNREACH ;
2258
+ case WSAENETRESET : return ENETRESET ;
2259
+ case WSAECONNABORTED : return ECONNABORTED ;
2260
+ case WSAECONNRESET : return ECONNRESET ;
2261
+ case WSAENOBUFS : return ENOBUFS ;
2262
+ case WSAEISCONN : return EISCONN ;
2263
+ case WSAENOTCONN : return ENOTCONN ;
2264
+ case WSAETIMEDOUT : return ETIMEDOUT ;
2265
+ case WSAECONNREFUSED : return ECONNREFUSED ;
2266
+ case WSAELOOP : return ELOOP ;
2267
+ case WSAENAMETOOLONG : return ENAMETOOLONG ;
2268
+ case WSAEHOSTUNREACH : return EHOSTUNREACH ;
2269
+ case WSAENOTEMPTY : return ENOTEMPTY ;
2270
+ /* No errno equivalent; default to EIO */
2271
+ case WSAESOCKTNOSUPPORT :
2272
+ case WSAEPFNOSUPPORT :
2273
+ case WSAESHUTDOWN :
2274
+ case WSAETOOMANYREFS :
2275
+ case WSAEHOSTDOWN :
2276
+ case WSAEPROCLIM :
2277
+ case WSAEUSERS :
2278
+ case WSAEDQUOT :
2279
+ case WSAESTALE :
2280
+ case WSAEREMOTE :
2281
+ case WSASYSNOTREADY :
2282
+ case WSAVERNOTSUPPORTED :
2283
+ case WSANOTINITIALISED :
2284
+ case WSAEDISCON :
2285
+ case WSAENOMORE :
2286
+ case WSAECANCELLED :
2287
+ case WSAEINVALIDPROCTABLE :
2288
+ case WSAEINVALIDPROVIDER :
2289
+ case WSAEPROVIDERFAILEDINIT :
2290
+ case WSASYSCALLFAILURE :
2291
+ case WSASERVICE_NOT_FOUND :
2292
+ case WSATYPE_NOT_FOUND :
2293
+ case WSA_E_NO_MORE :
2294
+ case WSA_E_CANCELLED :
2295
+ case WSAEREFUSED :
2296
+ case WSAHOST_NOT_FOUND :
2297
+ case WSATRY_AGAIN :
2298
+ case WSANO_RECOVERY :
2299
+ case WSANO_DATA :
2300
+ case WSA_QOS_RECEIVERS :
2301
+ case WSA_QOS_SENDERS :
2302
+ case WSA_QOS_NO_SENDERS :
2303
+ case WSA_QOS_NO_RECEIVERS :
2304
+ case WSA_QOS_REQUEST_CONFIRMED :
2305
+ case WSA_QOS_ADMISSION_FAILURE :
2306
+ case WSA_QOS_POLICY_FAILURE :
2307
+ case WSA_QOS_BAD_STYLE :
2308
+ case WSA_QOS_BAD_OBJECT :
2309
+ case WSA_QOS_TRAFFIC_CTRL_ERROR :
2310
+ case WSA_QOS_GENERIC_ERROR :
2311
+ case WSA_QOS_ESERVICETYPE :
2312
+ case WSA_QOS_EFLOWSPEC :
2313
+ case WSA_QOS_EPROVSPECBUF :
2314
+ case WSA_QOS_EFILTERSTYLE :
2315
+ case WSA_QOS_EFILTERTYPE :
2316
+ case WSA_QOS_EFILTERCOUNT :
2317
+ case WSA_QOS_EOBJLENGTH :
2318
+ case WSA_QOS_EFLOWCOUNT :
2319
+ #ifndef _MSC_VER
2320
+ case WSA_QOS_EUNKNOWNPSOBJ :
2321
+ #endif
2322
+ case WSA_QOS_EPOLICYOBJ :
2323
+ case WSA_QOS_EFLOWDESC :
2324
+ case WSA_QOS_EPSFLOWSPEC :
2325
+ case WSA_QOS_EPSFILTERSPEC :
2326
+ case WSA_QOS_ESDMODEOBJ :
2327
+ case WSA_QOS_ESHAPERATEOBJ :
2328
+ case WSA_QOS_RESERVED_PETYPE :
2329
+ default : return EIO ;
2330
+ }
2331
+ }
2332
+
2333
+ /*
2334
+ * On Windows, `errno` is a global macro to a function call.
2335
+ * This makes it difficult to debug and single-step our mappings.
2336
+ */
2337
+ static inline void set_wsa_errno (void )
2338
+ {
2339
+ DWORD wsa = WSAGetLastError ();
2340
+ int e = winsock_error_to_errno (wsa );
2341
+ errno = e ;
2342
+
2343
+ #ifdef DEBUG_WSA_ERRNO
2344
+ fprintf (stderr , "winsock error: %d -> %d\n" , wsa , e );
2345
+ fflush (stderr );
2346
+ #endif
2347
+ }
2348
+
2349
+ static inline int winsock_return (int ret )
2350
+ {
2351
+ if (ret < 0 )
2352
+ set_wsa_errno ();
2353
+
2354
+ return ret ;
2355
+ }
2356
+
2357
+ #define WINSOCK_RETURN (x ) do { return winsock_return(x); } while (0)
2358
+
2359
+ #undef strerror
2360
+ char * mingw_strerror (int errnum )
2361
+ {
2362
+ static char buf [41 ] = "" ;
2363
+ switch (errnum ) {
2364
+ case EWOULDBLOCK :
2365
+ xsnprintf (buf , 41 , "%s" , "Operation would block" );
2366
+ break ;
2367
+ case EINPROGRESS :
2368
+ xsnprintf (buf , 41 , "%s" , "Operation now in progress" );
2369
+ break ;
2370
+ case EALREADY :
2371
+ xsnprintf (buf , 41 , "%s" , "Operation already in progress" );
2372
+ break ;
2373
+ case ENOTSOCK :
2374
+ xsnprintf (buf , 41 , "%s" , "Socket operation on non-socket" );
2375
+ break ;
2376
+ case EDESTADDRREQ :
2377
+ xsnprintf (buf , 41 , "%s" , "Destination address required" );
2378
+ break ;
2379
+ case EMSGSIZE :
2380
+ xsnprintf (buf , 41 , "%s" , "Message too long" );
2381
+ break ;
2382
+ case EPROTOTYPE :
2383
+ xsnprintf (buf , 41 , "%s" , "Protocol wrong type for socket" );
2384
+ break ;
2385
+ case ENOPROTOOPT :
2386
+ xsnprintf (buf , 41 , "%s" , "Protocol not available" );
2387
+ break ;
2388
+ case EPROTONOSUPPORT :
2389
+ xsnprintf (buf , 41 , "%s" , "Protocol not supported" );
2390
+ break ;
2391
+ case EOPNOTSUPP :
2392
+ xsnprintf (buf , 41 , "%s" , "Operation not supported" );
2393
+ break ;
2394
+ case EAFNOSUPPORT :
2395
+ xsnprintf (buf , 41 , "%s" , "Address family not supported by protocol" );
2396
+ break ;
2397
+ case EADDRINUSE :
2398
+ xsnprintf (buf , 41 , "%s" , "Address already in use" );
2399
+ break ;
2400
+ case EADDRNOTAVAIL :
2401
+ xsnprintf (buf , 41 , "%s" , "Cannot assign requested address" );
2402
+ break ;
2403
+ case ENETDOWN :
2404
+ xsnprintf (buf , 41 , "%s" , "Network is down" );
2405
+ break ;
2406
+ case ENETUNREACH :
2407
+ xsnprintf (buf , 41 , "%s" , "Network is unreachable" );
2408
+ break ;
2409
+ case ENETRESET :
2410
+ xsnprintf (buf , 41 , "%s" , "Network dropped connection on reset" );
2411
+ break ;
2412
+ case ECONNABORTED :
2413
+ xsnprintf (buf , 41 , "%s" , "Software caused connection abort" );
2414
+ break ;
2415
+ case ECONNRESET :
2416
+ xsnprintf (buf , 41 , "%s" , "Connection reset by peer" );
2417
+ break ;
2418
+ case ENOBUFS :
2419
+ xsnprintf (buf , 41 , "%s" , "No buffer space available" );
2420
+ break ;
2421
+ case EISCONN :
2422
+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is already connected" );
2423
+ break ;
2424
+ case ENOTCONN :
2425
+ xsnprintf (buf , 41 , "%s" , "Transport endpoint is not connected" );
2426
+ break ;
2427
+ case ETIMEDOUT :
2428
+ xsnprintf (buf , 41 , "%s" , "Connection timed out" );
2429
+ break ;
2430
+ case ECONNREFUSED :
2431
+ xsnprintf (buf , 41 , "%s" , "Connection refused" );
2432
+ break ;
2433
+ case ELOOP :
2434
+ xsnprintf (buf , 41 , "%s" , "Too many levels of symbolic links" );
2435
+ break ;
2436
+ case EHOSTUNREACH :
2437
+ xsnprintf (buf , 41 , "%s" , "No route to host" );
2438
+ break ;
2439
+ default : return strerror (errnum );
2440
+ }
2441
+ return buf ;
2442
+ }
2443
+
2234
2444
#undef gethostname
2235
2445
int mingw_gethostname (char * name , int namelen )
2236
2446
{
2237
- ensure_socket_initialization ();
2238
- return gethostname (name , namelen );
2447
+ ensure_socket_initialization ();
2448
+ WINSOCK_RETURN ( gethostname (name , namelen ) );
2239
2449
}
2240
2450
2241
2451
#undef gethostbyname
2242
2452
struct hostent * mingw_gethostbyname (const char * host )
2243
2453
{
2454
+ struct hostent * ret ;
2455
+
2244
2456
ensure_socket_initialization ();
2245
- return gethostbyname (host );
2457
+
2458
+ ret = gethostbyname (host );
2459
+ if (!ret )
2460
+ set_wsa_errno ();
2461
+
2462
+ return ret ;
2246
2463
}
2247
2464
2248
2465
#undef getaddrinfo
2249
2466
int mingw_getaddrinfo (const char * node , const char * service ,
2250
2467
const struct addrinfo * hints , struct addrinfo * * res )
2251
2468
{
2252
2469
ensure_socket_initialization ();
2253
- return getaddrinfo (node , service , hints , res );
2470
+ WINSOCK_RETURN ( getaddrinfo (node , service , hints , res ) );
2254
2471
}
2255
2472
2256
2473
int mingw_socket (int domain , int type , int protocol )
@@ -2261,16 +2478,7 @@ int mingw_socket(int domain, int type, int protocol)
2261
2478
ensure_socket_initialization ();
2262
2479
s = WSASocket (domain , type , protocol , NULL , 0 , 0 );
2263
2480
if (s == INVALID_SOCKET ) {
2264
- /*
2265
- * WSAGetLastError() values are regular BSD error codes
2266
- * biased by WSABASEERR.
2267
- * However, strerror() does not know about networking
2268
- * specific errors, which are values beginning at 38 or so.
2269
- * Therefore, we choose to leave the biased error code
2270
- * in errno so that _if_ someone looks up the code somewhere,
2271
- * then it is at least the number that are usually listed.
2272
- */
2273
- errno = WSAGetLastError ();
2481
+ set_wsa_errno ();
2274
2482
return -1 ;
2275
2483
}
2276
2484
/* convert into a file descriptor */
@@ -2286,35 +2494,35 @@ int mingw_socket(int domain, int type, int protocol)
2286
2494
int mingw_connect (int sockfd , struct sockaddr * sa , size_t sz )
2287
2495
{
2288
2496
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2289
- return connect (s , sa , sz );
2497
+ WINSOCK_RETURN ( connect (s , sa , sz ) );
2290
2498
}
2291
2499
2292
2500
#undef bind
2293
2501
int mingw_bind (int sockfd , struct sockaddr * sa , size_t sz )
2294
2502
{
2295
2503
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2296
- return bind (s , sa , sz );
2504
+ WINSOCK_RETURN ( bind (s , sa , sz ) );
2297
2505
}
2298
2506
2299
2507
#undef setsockopt
2300
2508
int mingw_setsockopt (int sockfd , int lvl , int optname , void * optval , int optlen )
2301
2509
{
2302
2510
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2303
- return setsockopt (s , lvl , optname , (const char * )optval , optlen );
2511
+ WINSOCK_RETURN ( setsockopt (s , lvl , optname , (const char * )optval , optlen ) );
2304
2512
}
2305
2513
2306
2514
#undef shutdown
2307
2515
int mingw_shutdown (int sockfd , int how )
2308
2516
{
2309
2517
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2310
- return shutdown (s , how );
2518
+ WINSOCK_RETURN ( shutdown (s , how ) );
2311
2519
}
2312
2520
2313
2521
#undef listen
2314
2522
int mingw_listen (int sockfd , int backlog )
2315
2523
{
2316
2524
SOCKET s = (SOCKET )_get_osfhandle (sockfd );
2317
- return listen (s , backlog );
2525
+ WINSOCK_RETURN ( listen (s , backlog ) );
2318
2526
}
2319
2527
2320
2528
#undef accept
@@ -2325,6 +2533,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
2325
2533
SOCKET s1 = (SOCKET )_get_osfhandle (sockfd1 );
2326
2534
SOCKET s2 = accept (s1 , sa , sz );
2327
2535
2536
+ if (s2 == INVALID_SOCKET ) {
2537
+ set_wsa_errno ();
2538
+ return -1 ;
2539
+ }
2540
+
2328
2541
/* convert into a file descriptor */
2329
2542
if ((sockfd2 = _open_osfhandle (s2 , O_RDWR |O_BINARY )) < 0 ) {
2330
2543
int err = errno ;
0 commit comments