access: bluray: only copy visible extents
[vlc.git] / compat / sendmsg.c
blob0b08ce0942026b9642da43c548bd4ee35c451da5
1 /*****************************************************************************
2 * sendmsg.c: POSIX sendmsg() 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 sendmsg(int fd, const 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 = (void *)msg->msg_iov[i].iov_base;
58 DWORD sent;
60 int ret = WSASendTo(fd, buf, msg->msg_iovlen, &sent, flags,
61 msg->msg_name, msg->msg_namelen, NULL, NULL);
62 free(buf);
64 if (ret == 0)
65 return sent;
67 switch (WSAGetLastError())
69 case WSAEWOULDBLOCK:
70 errno = EAGAIN;
71 break;
73 return -1;
76 #elif defined __native_client__
77 #include <errno.h>
78 #include <limits.h>
79 #include <stdlib.h>
80 #include <string.h>
81 #ifdef HAVE_SYS_SOCKET_H
82 #include <sys/socket.h>
83 #endif
84 #ifdef HAVE_SYS_UIO_H
85 #include <sys/uio.h>
86 #endif
88 ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
90 if (msg->msg_controllen != 0)
92 errno = ENOSYS;
93 return -1;
96 if ((msg->msg_iovlen <= 0) || (msg->msg_iovlen > IOV_MAX))
98 errno = EMSGSIZE;
99 return -1;
102 size_t full_size = 0;
103 for (int i = 0; i < msg->msg_iovlen; ++i)
104 full_size += msg->msg_iov[i].iov_len;
106 if (full_size > SSIZE_MAX) {
107 errno = EINVAL;
108 return -1;
112 * We always allocate here, because whether send/sento allow NULL message or
113 * not is unspecified.
115 char *data = malloc(full_size ? full_size : 1);
116 if (!data) {
117 errno = ENOMEM;
118 return -1;
121 size_t tmp = 0;
122 for (int i = 0; i < msg->msg_iovlen; ++i) {
123 memcpy(data + tmp, msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
124 tmp += msg->msg_iov[i].iov_len;
127 ssize_t res;
128 if (msg->msg_name)
129 res = sendto(fd, data, full_size, flags, msg->msg_name, msg->msg_namelen);
130 else
131 res = send(fd, data, full_size, flags);
133 free(data);
134 return res;
137 #else
138 #error sendmsg not implemented on your platform!
139 #endif