windows: Wrap most Winsock2 Posix functions to set errno

While Winsock provides many Posix compatibility functions, they do not set
errno, but use WSAGetLastError() for error reporting. The wrapped functions
derive an errno from WSAGetLastError() on failure.
This commit is contained in:
Martin Willi 2014-06-11 11:08:03 +02:00
parent bc1139480f
commit 8b5d41a274
2 changed files with 198 additions and 65 deletions

View File

@ -316,74 +316,66 @@ static int wserr(int retval)
{
if (retval < 0)
{
switch (WSAGetLastError())
static const struct {
DWORD wsa;
int err;
} map[] = {
{ WSANOTINITIALISED, EBADF },
{ WSAENETDOWN, ENETDOWN },
{ WSAENETRESET, ENETRESET },
{ WSAECONNABORTED, ECONNABORTED },
{ WSAESHUTDOWN, ECONNABORTED },
{ WSAEACCES, EACCES },
{ WSAEINTR, EINTR },
{ WSAEINPROGRESS, EINPROGRESS },
{ WSAEFAULT, EFAULT },
{ WSAENOBUFS, ENOBUFS },
{ WSAENOTSOCK, ENOTSOCK },
{ WSAEOPNOTSUPP, EOPNOTSUPP },
{ WSAEWOULDBLOCK, EWOULDBLOCK },
{ WSAEMSGSIZE, EMSGSIZE },
{ WSAEINVAL, EINVAL },
{ WSAENOTCONN, ENOTCONN },
{ WSAEHOSTUNREACH, EHOSTUNREACH },
{ WSAENETUNREACH, ENETUNREACH },
{ WSAECONNABORTED, ECONNABORTED },
{ WSAECONNRESET, ECONNRESET },
{ WSAETIMEDOUT, ETIMEDOUT },
{ WSAEMFILE, EMFILE },
{ WSAEALREADY, EALREADY },
{ WSAEDESTADDRREQ, EDESTADDRREQ },
{ WSAEISCONN, EISCONN },
{ WSAEOPNOTSUPP, EOPNOTSUPP },
{ WSAEPROTOTYPE, EPROTOTYPE },
{ WSAENOPROTOOPT, ENOPROTOOPT },
{ WSAEPROTONOSUPPORT, EPROTONOSUPPORT },
{ WSAEPFNOSUPPORT, EPROTONOSUPPORT },
{ WSAEAFNOSUPPORT, EAFNOSUPPORT },
{ WSAEADDRNOTAVAIL, EADDRNOTAVAIL },
{ WSAEADDRINUSE, EADDRINUSE },
{ WSAETIMEDOUT, ETIMEDOUT },
{ WSAECONNREFUSED, ECONNREFUSED },
{ WSAELOOP, ELOOP },
{ WSAENAMETOOLONG, ENAMETOOLONG },
{ WSAENOTEMPTY, ENOTEMPTY },
{ WSAEPROTOTYPE, EPROTOTYPE },
{ WSAVERNOTSUPPORTED, ENOTSUP },
};
DWORD wsa, i;
wsa = WSAGetLastError();
for (i = 0; i < countof(map); i++)
{
case WSANOTINITIALISED:
errno = EBADF;
break;
case WSAENETDOWN:
errno = ENETDOWN;
break;
case WSAENETRESET:
errno = ENETRESET;
break;
case WSAESHUTDOWN:
errno = ECONNABORTED;
break;
case WSAEACCES:
errno = EACCES;
break;
case WSAEINTR:
errno = EINTR;
break;
case WSAEINPROGRESS:
errno = EINPROGRESS;
break;
case WSAEFAULT:
errno = EFAULT;
break;
case WSAENOBUFS:
errno = ENOBUFS;
break;
case WSAENOTSOCK:
errno = ENOTSOCK;
break;
case WSAEOPNOTSUPP:
errno = EOPNOTSUPP;
break;
case WSAEWOULDBLOCK:
errno = EWOULDBLOCK;
break;
case WSAEMSGSIZE:
errno = EMSGSIZE;
break;
case WSAEINVAL:
errno = EINVAL;
break;
case WSAENOTCONN:
errno = ENOTCONN;
break;
case WSAEHOSTUNREACH:
errno = EHOSTUNREACH;
break;
case WSAECONNABORTED:
errno = ECONNABORTED;
break;
case WSAECONNRESET:
errno = ECONNRESET;
break;
case WSAETIMEDOUT:
errno = ETIMEDOUT;
break;
default:
errno = ENOENT;
break;
if (map[i].wsa == wsa)
{
errno = map[i].err;
return retval;
}
}
errno = ENOENT;
return retval;
}
else
{
errno = 0;
}
errno = 0;
return retval;
}
@ -400,6 +392,90 @@ static bool check_dontwait(int *flags)
return FALSE;
}
/**
* See header
*/
#undef shutdown
int windows_shutdown(int sockfd, int how)
{
return wserr(shutdown(sockfd, how));
}
/**
* See header
*/
#undef accept
int windows_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
return wserr(accept(sockfd, addr, addrlen));
}
/**
* See header
*/
#undef bind
int windows_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
return wserr(bind(sockfd, addr, addrlen));
}
/**
* See header
*/
#undef connect
int windows_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
return wserr(connect(sockfd, addr, addrlen));
}
/**
* See header
*/
#undef getsockname
int windows_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
return wserr(getsockname(sockfd, addr, addrlen));
}
/**
* See header
*/
#undef getsockopt
int windows_getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen)
{
return wserr(getsockopt(sockfd, level, optname, optval, optlen));
}
/**
* See header
*/
#undef setsockopt
int windows_setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen)
{
return wserr(setsockopt(sockfd, level, optname, optval, optlen));
}
/**
* See header
*/
#undef socket
int windows_socket(int domain, int type, int protocol)
{
return wserr(socket(domain, type, protocol));
}
/**
* See header
*/
#undef select
int windows_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout)
{
return wserr(select(nfds, readfds, writefds, exceptfds, timeout));
}
/**
* See header
*/

View File

@ -272,6 +272,63 @@ char* getpass(const char *prompt);
#define SHUT_WR SD_SEND
#define SHUT_RDWR SD_BOTH
/**
* shutdown(2) setting errno
*/
#define shutdown windows_shutdown
int windows_shutdown(int sockfd, int how);
/**
* accept(2) setting errno
*/
#define accept windows_accept
int windows_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
/**
* bind(2) setting errno
*/
#define bind windows_bind
int windows_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/**
* connect(2) setting errno
*/
#define connect windows_connect
int windows_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/**
* getsockname(2) setting errno
*/
#define getsockname windows_getsockname
int windows_getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
/**
* getsockopt(2) setting errno
*/
#define getsockopt windows_getsockopt
int windows_getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
/**
* setsockopt(2) setting errno
*/
#define setsockopt windows_setsockopt
int windows_setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
/**
* socket(2) setting errno
*/
#define socket windows_socket
int windows_socket(int domain, int type, int protocol);
/**
* select(2) setting errno
*/
#define select windows_select
int windows_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
/**
* close(2) working for file handles and Winsock sockets
*/