1 #ifndef foowincompatfoo
2 #define foowincompatfoo
4 // This file and its companion wincompat.c provide some Posix interfaces to
5 // Windows APIs so the rest of the code can keep using them.
8 // require at least Windows Vista
12 #define _WIN32_WINNT WINVER
17 #include <sys/types.h>
19 // TODO: fix mingw32 x86 or drop support and use x86_x64
20 // copied from x86_64-4.8.3-release-posix-seh-rt_v3-rev0 for mingw32 x86 4.8.1
21 #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
23 #define POLLRDNORM 0x0100
24 #define POLLRDBAND 0x0200
25 #define POLLIN (POLLRDNORM | POLLRDBAND)
26 #define POLLPRI 0x0400
28 #define POLLWRNORM 0x0010
29 #define POLLOUT (POLLWRNORM)
30 #define POLLWRBAND 0x0020
32 #define POLLERR 0x0001
33 #define POLLHUP 0x0002
34 #define POLLNVAL 0x0004
36 typedef struct pollfd {
40 } WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
42 // to fix redefenition of 'timespec' defined in pthread.h and parts/time.h used by simple-watch.c
43 #define HAVE_STRUCT_TIMESPEC
46 #define IPV6_HOPOPTS 1
47 #define IPV6_HDRINCL 2
48 #define IPV6_UNICAST_HOPS 4
49 #define IPV6_MULTICAST_IF 9
50 #define IPV6_MULTICAST_HOPS 10
51 #define IPV6_MULTICAST_LOOP 11
52 #define IPV6_ADD_MEMBERSHIP 12
53 #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
54 #define IPV6_DROP_MEMBERSHIP 13
55 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
56 #define IPV6_DONTFRAG 14
57 #define IPV6_PKTINFO 19
58 #define IPV6_HOPLIMIT 21
59 #define IPV6_PROTECTION_LEVEL 23
60 #define IPV6_RECVIF 24
61 #define IPV6_RECVDSTADDR 25
62 #define IPV6_CHECKSUM 26
63 #define IPV6_V6ONLY 27
64 #define IPV6_IFLIST 28
65 #define IPV6_ADD_IFLIST 29
66 #define IPV6_DEL_IFLIST 30
67 #define IPV6_UNICAST_IF 31
69 #define IPV6_RECVRTHDR 38
70 #define IPV6_TCLASS 39
71 #define IPV6_RECVTCLASS 40
75 #define EADDRINUSE 100
79 #define EWOULDBLOCK 140
83 #define MSG_TRUNC 0x0100
84 #define MSG_CTRUNC 0x0200
87 //.... lots of dependencies x-(
88 // TODO: fix mingw32 x86 or drop support and use x86_x64
92 // wrappers around WSAStartup/WSACleanup to avoid clutter
93 void winsock_init(void);
94 void winsock_exit(void);
97 // the equivalent of strerror(errno) for Windows sockets
98 char *errnostrsocket(void);
101 // Winsock doesn't have recvmsg/sendmsg but offers the same functionality
102 // with WSARecvMsg/WSASendMsg, so we implement the former in terms of the
105 struct iovec { /* Scatter/gather array items */
106 void *iov_base; /* Starting address */
107 size_t iov_len; /* Number of bytes to transfer */
111 void *msg_name; /* optional address */
112 socklen_t msg_namelen; /* size of address */
113 struct iovec *msg_iov; /* scatter/gather array */
114 size_t msg_iovlen; /* # elements in msg_iov */
115 void *msg_control; /* ancillary data, see below */
116 size_t msg_controllen; /* ancillary data buffer len */
117 int msg_flags; /* flags on received message */
120 // MSDN says this struct is called wsacmsghdr but MingW uses _WSACMSGHDR.
121 // TODO: Verify what it is on actual Windows.
122 // cf. http://msdn.microsoft.com/en-us/library/ms741645(v=vs.85).aspx
124 // MingW32 x86 4.8.1 uses wsacmsghdr, MingW x86_x64 uses _WSACMSGHDR and Visual Studio 2015 RC (ws2def.h) defines:
125 // #if(_WIN32_WINNT >= 0x0600)
126 // #define _WSACMSGHDR cmsghdr
127 // #endif //(_WIN32_WINNT>=0x0600)
128 // typedef struct _WSACMSGHDR {
132 // /* followed by UCHAR cmsg_data[] */
133 // } WSACMSGHDR, *PWSACMSGHDR, FAR *LPWSACMSGHDR;
135 #ifdef __MINGW64_VERSION_MAJOR
136 #define cmsghdr _WSACMSGHDR // as in 'struct cmsghdr'
138 #define cmsghdr wsacmsghdr // as in 'struct cmsghdr'
140 #elif (_WIN32_WINNT < 0x0600)
141 #define cmsghdr _WSACMSGHDR
144 // VS2015 ws2def.h already defines: #define CMSG_FIRSTHDR WSA_CMSG_FIRSTHDR
148 static inline struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *m) {
150 wm.Control.len = m->msg_controllen;
151 wm.Control.buf = (char*)m->msg_control;
152 return WSA_CMSG_FIRSTHDR(&wm);
155 // VS2015 ws2def.h already defines: #define CMSG_NXTHDR WSA_CMSG_NXTHDR
159 static inline struct cmsghdr *CMSG_NXTHDR(struct msghdr *m, struct cmsghdr *c) {
161 wm.Control.len = m->msg_controllen;
162 wm.Control.buf = (char*)m->msg_control;
163 return WSA_CMSG_NXTHDR(&wm, c);
167 #define CMSG_SPACE(len) WSA_CMSG_SPACE(len)
170 #define CMSG_LEN(len) WSA_CMSG_LEN(len)
173 // we're going to be naughty and redefine CMSG_DATA as an alias even though it
174 // is also a constant defined in wincrypt.h which we don't care about.
176 #define CMSG_DATA(c) WSA_CMSG_DATA(c)
178 // VS2012 and up has no ssize_t defined, before it was defined as unsigned int
181 typedef signed int ssize_t;
184 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
185 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
187 // ESHUTDOWN does not seem to exist on Windows, even though WSAESHUTDOWN does.
188 // MingW doesn't define it and MSDN doesn't list it, so we alias it to EBADF.
189 // cf. http://msdn.microsoft.com/en-us/library/5814770t.aspx
191 #define ESHUTDOWN EBADF
195 // Windows doesn't have ioctl but offers ioctlsocket for some socket-related
196 // functions. Unfortunately, argument types differ, so we implement a
197 // (restricted) wrapper.
198 int ioctl(int d, unsigned long request, int *p);
201 // Windows lacks poll, but WSAPoll is good enough for us.
202 #define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
204 // Windows lacks pipe. It has an equivalent CreatePipe but we really need
205 // something to give to WSAPoll, so we fake it with a local TCP socket. (ugh)
206 int pipe(int pipefd[2]);
208 // pipe(socket)-specific read/write/close equivalents
209 #define closepipe closesocket
210 #define writepipe(s,buf,len) send(s, buf, len, 0)
211 #define readpipe(s,buf,len) recv(s, buf, len, 0)
214 // Windows logically doesn't have uname, so we supply a replacement.
217 char sysname[9]; /* Operating system name (e.g., "Linux") */
218 char nodename[MAX_COMPUTERNAME_LENGTH+1];
219 /* Name within "some implementation-defined network" */
220 char release[9]; /* Operating system release (e.g., "2.6.28") */
221 char version[9]; /* Operating system version */
222 char machine[9]; /* Hardware identifier */
225 int uname(struct utsname *buf);