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