Update LibreSSL from version 2.4.3 => 2.4.4
[dragonfly.git] / crypto / libressl / crypto / compat / posix_win.c
1 /*
2  * Public domain
3  *
4  * BSD socket emulation code for Winsock2
5  * File IO compatibility shims
6  * Brent Cook <bcook@openbsd.org>
7  */
8
9 #define NO_REDEF_POSIX_FUNCTIONS
10
11 #include <windows.h>
12 #include <ws2tcpip.h>
13
14 #include <errno.h>
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20
21 void
22 posix_perror(const char *s)
23 {
24         fprintf(stderr, "%s: %s\n", s, strerror(errno));
25 }
26
27 FILE *
28 posix_fopen(const char *path, const char *mode)
29 {
30         if (strchr(mode, 'b') == NULL) {
31                 char *bin_mode = NULL;
32                 if (asprintf(&bin_mode, "%sb", mode) == -1)
33                         return NULL;
34                 FILE *f = fopen(path, bin_mode);
35                 free(bin_mode);
36                 return f;
37         }
38
39         return fopen(path, mode);
40 }
41
42 char *
43 posix_fgets(char *s, int size, FILE *stream)
44 {
45         char *ret = fgets(s, size, stream);
46         if (ret != NULL) {
47                 size_t end = strlen(ret);
48                 if (end >= 2 && ret[end - 2] == '\r' && ret[end - 1] == '\n') {
49                         ret[end - 2] = '\n';
50                         ret[end - 1] = '\0';
51                 }
52         }
53         return ret;
54 }
55
56 int
57 posix_rename(const char *oldpath, const char *newpath)
58 {
59         return MoveFileEx(oldpath, newpath, MOVEFILE_REPLACE_EXISTING) ? 0 : -1;
60 }
61
62 static int
63 wsa_errno(int err)
64 {
65         switch (err) {
66         case WSAENOBUFS:
67                 errno = ENOMEM;
68                 break;
69         case WSAEACCES:
70                 errno = EACCES;
71                 break;
72         case WSANOTINITIALISED:
73                 errno = EPERM;
74                 break;
75         case WSAEHOSTUNREACH:
76         case WSAENETDOWN:
77                 errno = EIO;
78                 break;
79         case WSAEFAULT:
80                 errno = EFAULT;
81                 break;
82         case WSAEINTR:
83                 errno = EINTR;
84                 break;
85         case WSAEINVAL:
86                 errno = EINVAL;
87                 break;
88         case WSAEINPROGRESS:
89                 errno = EINPROGRESS;
90                 break;
91         case WSAEWOULDBLOCK:
92                 errno = EAGAIN;
93                 break;
94         case WSAEOPNOTSUPP:
95                 errno = ENOTSUP;
96                 break;
97         case WSAEMSGSIZE:
98                 errno = EFBIG;
99                 break;
100         case WSAENOTSOCK:
101                 errno = ENOTSOCK;
102                 break;
103         case WSAENOPROTOOPT:
104                 errno = ENOPROTOOPT;
105                 break;
106         case WSAECONNREFUSED:
107                 errno = ECONNREFUSED;
108                 break;
109         case WSAEAFNOSUPPORT:
110                 errno = EAFNOSUPPORT;
111                 break;
112         case WSAENETRESET:
113         case WSAENOTCONN:
114         case WSAECONNABORTED:
115         case WSAECONNRESET:
116         case WSAESHUTDOWN:
117         case WSAETIMEDOUT:
118                 errno = EPIPE;
119                 break;
120         }
121         return -1;
122 }
123
124 int
125 posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
126 {
127         int rc = connect(sockfd, addr, addrlen);
128         if (rc == SOCKET_ERROR)
129                 return wsa_errno(WSAGetLastError());
130         return rc;
131 }
132
133 int
134 posix_close(int fd)
135 {
136         if (closesocket(fd) == SOCKET_ERROR) {
137                 int err = WSAGetLastError();
138                 return err == WSAENOTSOCK ?
139                         close(fd) : wsa_errno(err);
140         }
141         return 0;
142 }
143
144 ssize_t
145 posix_read(int fd, void *buf, size_t count)
146 {
147         ssize_t rc = recv(fd, buf, count, 0);
148         if (rc == SOCKET_ERROR) {
149                 int err = WSAGetLastError();
150                 return err == WSAENOTSOCK ?
151                         read(fd, buf, count) : wsa_errno(err);
152         }
153         return rc;
154 }
155
156 ssize_t
157 posix_write(int fd, const void *buf, size_t count)
158 {
159         ssize_t rc = send(fd, buf, count, 0);
160         if (rc == SOCKET_ERROR) {
161                 int err = WSAGetLastError();
162                 return err == WSAENOTSOCK ?
163                         write(fd, buf, count) : wsa_errno(err);
164         }
165         return rc;
166 }
167
168 int
169 posix_getsockopt(int sockfd, int level, int optname,
170         void *optval, socklen_t *optlen)
171 {
172         int rc = getsockopt(sockfd, level, optname, (char *)optval, optlen);
173         return rc == 0 ? 0 : wsa_errno(WSAGetLastError());
174
175 }
176
177 int
178 posix_setsockopt(int sockfd, int level, int optname,
179         const void *optval, socklen_t optlen)
180 {
181         int rc = setsockopt(sockfd, level, optname, (char *)optval, optlen);
182         return rc == 0 ? 0 : wsa_errno(WSAGetLastError());
183 }
184
185 #ifdef _MSC_VER
186 int gettimeofday(struct timeval * tp, struct timezone * tzp)
187 {
188         /*
189          * Note: some broken versions only have 8 trailing zero's, the correct
190          * epoch has 9 trailing zero's
191          */
192         static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);
193
194         SYSTEMTIME  system_time;
195         FILETIME    file_time;
196         uint64_t    time;
197
198         GetSystemTime(&system_time);
199         SystemTimeToFileTime(&system_time, &file_time);
200         time = ((uint64_t)file_time.dwLowDateTime);
201         time += ((uint64_t)file_time.dwHighDateTime) << 32;
202
203         tp->tv_sec = (long)((time - EPOCH) / 10000000L);
204         tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
205         return 0;
206 }
207
208 unsigned int sleep(unsigned int seconds)
209 {
210         Sleep(seconds * 1000);
211         return seconds;
212 }
213
214 #endif