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