macOS: Add swapoutOverride function to CompatibilityFixes
[vlc.git] / compat / recvmsg.c
blobaefeb93e9c5fe02cdcbb3414c18ee641f78cde45
1 /*****************************************************************************
2 * recvmsg.c: POSIX recvmsg() replacement
3 *****************************************************************************
4 * Copyright © 2017 VLC authors and VideoLAN
5 * Copyright © 2016 Rémi Denis-Courmont
7 * Authors: Rémi Denis-Courmont
8 * Dennis Hamester <dhamester@jusst.de>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
29 #ifdef _WIN32
30 # include <errno.h>
31 # include <stdlib.h>
32 # include <winsock2.h>
34 ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
36 if (msg->msg_controllen != 0)
38 errno = ENOSYS;
39 return -1;
42 if (msg->msg_iovlen > IOV_MAX)
44 errno = EINVAL;
45 return -1;
48 WSABUF *buf = malloc(msg->msg_iovlen * sizeof (*buf));
49 if (buf == NULL)
50 return -1;
52 for (unsigned i = 0; i < msg->msg_iovlen; i++)
54 buf[i].len = msg->msg_iov[i].iov_len;
55 buf[i].buf = msg->msg_iov[i].iov_base;
58 DWORD dwFlags = flags;
59 INT fromlen = msg->msg_namelen;
60 DWORD rcvd;
61 int ret;
62 if (fromlen)
63 ret = WSARecvFrom(fd, buf, msg->msg_iovlen, &rcvd, &dwFlags,
64 msg->msg_name, &fromlen, NULL, NULL);
65 else
66 ret = WSARecv(fd, buf, msg->msg_iovlen, &rcvd, &dwFlags,
67 NULL, NULL);
68 free(buf);
70 if (ret == 0)
72 msg->msg_namelen = fromlen;
73 msg->msg_flags = dwFlags;
74 return rcvd;
77 switch (WSAGetLastError())
79 case WSAEWOULDBLOCK:
80 errno = EAGAIN;
81 break;
83 return -1;
86 #elif __native_client__
87 #include <errno.h>
88 #include <limits.h>
89 #include <stdlib.h>
90 #include <string.h>
91 #include <sys/socket.h>
92 #include <sys/uio.h>
94 ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
96 if (msg->msg_controllen != 0)
98 errno = ENOSYS;
99 return -1;
102 if ((msg->msg_iovlen <= 0) || (msg->msg_iovlen > IOV_MAX))
104 errno = EMSGSIZE;
105 return -1;
108 size_t full_size = 0;
109 for (int i = 0; i < msg->msg_iovlen; ++i)
110 full_size += msg->msg_iov[i].iov_len;
112 if (full_size > SSIZE_MAX) {
113 errno = EINVAL;
114 return -1;
118 * We always allocate here, because whether recv/recvfrom allow NULL message
119 * or not is unspecified.
121 char *data = malloc(full_size ? full_size : 1);
122 if (!data) {
123 errno = ENOMEM;
124 return -1;
127 ssize_t res;
128 if (msg->msg_name)
129 res = recvfrom(fd, data, full_size, flags, msg->msg_name, &msg->msg_namelen);
130 else
131 res = recv(fd, data, full_size, flags);
133 if (res > 0) {
134 size_t left;
135 if ((size_t)res <= full_size) {
136 left = res;
137 msg->msg_flags = 0;
139 else {
140 left = full_size;
141 msg->msg_flags = MSG_TRUNC;
144 const char *src = data;
145 for (int i = 0; (i < msg->msg_iovlen) && (left > 0); ++i)
147 size_t to_copy = msg->msg_iov[i].iov_len;
148 if (to_copy > left)
149 to_copy = left;
151 memcpy(msg->msg_iov[i].iov_base, src, to_copy);
152 src += to_copy;
153 left -= to_copy;
157 free(data);
158 return res;
161 #else
162 #error recvmsg not implemented on your platform!
163 #endif