7 // helper: convert WSAGetLastError() to an errno constant
8 static int wsa_errno(void)
10 switch(WSAGetLastError()) {
11 case WSAECONNRESET: return ECONNRESET;
12 case WSAEFAULT: return EFAULT;
13 case WSAEINPROGRESS: return EINPROGRESS;
14 case WSAEINTR: return EINTR;
15 case WSAEINVAL: return EINVAL;
16 case WSAEMSGSIZE: return EMSGSIZE;
17 case WSAENETDOWN: return ENETDOWN;
18 case WSAENETRESET: return ENETRESET;
19 case WSAENOTCONN: return ENOTCONN;
20 case WSAENOTSOCK: return ENOTSOCK;
21 case WSAEOPNOTSUPP: return EOPNOTSUPP;
22 case WSAEWOULDBLOCK: return EWOULDBLOCK;
28 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
30 LPFN_WSARECVMSG WSARecvMsg = NULL;
31 GUID wsaid = WSAID_WSARECVMSG;
39 // size_t is larger than DWORD on 64bit
40 if(msg->msg_iovlen > UINT32_MAX) {
45 // obtain the function pointer to WSARecvMsg
46 r = WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
47 &wsaid, sizeof(wsaid), &WSARecvMsg, sizeof(WSARecvMsg),
49 if(r == SOCKET_ERROR) {
53 assert(b == sizeof(WSARecvMsg));
54 assert(WSARecvMsg != NULL);
56 // convert msghdr to WSAMSG structure
57 wsamsg.name = msg->msg_name;
58 wsamsg.namelen = msg->msg_namelen;
59 wsamsg.lpBuffers = malloc(msg->msg_iovlen * sizeof(WSABUF));
60 wsamsg.dwBufferCount = msg->msg_iovlen;
61 wsamsg.Control.len = msg->msg_controllen;
62 wsamsg.Control.buf = msg->msg_control;
63 wsamsg.dwFlags = (DWORD)flags;
65 // all flags that fit into dwFlags also fit through the flags argument
66 assert(sizeof(DWORD) <= sizeof(flags));
68 if(wsamsg.lpBuffers == NULL) {
69 // malloc will have set errno
73 // re-wrap iovecs as WSABUFs
74 for(i=0; i<msg->msg_iovlen; i++) {
76 if(msg->msg_iov[i].iov_len > ULONG_MAX) {
77 free(wsamsg.lpBuffers);
82 wsamsg.lpBuffers[i].len = msg->msg_iov[i].iov_len;
83 wsamsg.lpBuffers[i].buf = msg->msg_iov[i].iov_base;
86 r = WSARecvMsg(sockfd, &wsamsg, &bytesrcvd, NULL, NULL);
88 // the allocated WSABUF wrappers are no longer needed
89 free(wsamsg.lpBuffers);
91 if(r == SOCKET_ERROR) {
92 // XXX do we need special handling for ENETRESET, EMSGSIZE, ETIMEDOUT?
97 // DWORD has one bit more than ssize_t on 32bit
98 if(bytesrcvd > SSIZE_MAX) {
103 // transfer results from wsamsg to msg
104 // NB: the data and control buffers are shared
105 msg->msg_controllen = wsamsg.Control.len;
106 msg->msg_flags = (int)wsamsg.dwFlags;
107 // all flags that fit into dwFlags also fit into msg_flags (see above)
112 int uname(struct utsname *buf)
115 const char *arch = "unknown";
117 memset(buf, 0, sizeof(struct utsname));
120 strncpy(buf->sysname, "Windows", sizeof(buf->sysname)-1);
121 strncpy(buf->release, "unknown", sizeof(buf->sysname)-1); // we don't need it
122 strncpy(buf->version, "unknown", sizeof(buf->sysname)-1); // we don't need it
124 // computer (node) name
125 if(GetComputerName(buf->nodename, sizeof(buf->nodename)-1) == 0) {
132 switch(si.wProcessorArchitecture) {
133 case PROCESSOR_ARCHITECTURE_AMD64: arch = "amd64"; break;
134 case PROCESSOR_ARCHITECTURE_ARM: arch = "arm"; break;
135 case PROCESSOR_ARCHITECTURE_IA64: arch = "ia64"; break;
136 case PROCESSOR_ARCHITECTURE_INTEL: arch = "x86"; break;
137 default: arch = "unknown";
139 strncpy(buf->machine, arch, sizeof(buf->machine)-1);