]>
Commit | Line | Data |
---|---|---|
320054e8 DG |
1 | #define _GNU_SOURCE |
2 | #include <sys/socket.h> | |
3 | #include <limits.h> | |
79a9b408 DG |
4 | #include <errno.h> |
5 | #include <time.h> | |
320054e8 DG |
6 | #include "syscall.h" |
7 | ||
79a9b408 DG |
8 | #define IS32BIT(x) !((x)+0x80000000ULL>>32) |
9 | #define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63)) | |
10 | ||
575e1579 DG |
11 | hidden void __convert_scm_timestamps(struct msghdr *, socklen_t); |
12 | ||
320054e8 DG |
13 | int recvmmsg(int fd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int flags, struct timespec *timeout) |
14 | { | |
15 | #if LONG_MAX > INT_MAX | |
16 | struct mmsghdr *mh = msgvec; | |
17 | unsigned int i; | |
18 | for (i = vlen; i; i--, mh++) | |
19 | mh->msg_hdr.__pad1 = mh->msg_hdr.__pad2 = 0; | |
20 | #endif | |
79a9b408 DG |
21 | #ifdef SYS_recvmmsg_time64 |
22 | time_t s = timeout ? timeout->tv_sec : 0; | |
23 | long ns = timeout ? timeout->tv_nsec : 0; | |
575e1579 | 24 | int r = __syscall_cp(SYS_recvmmsg_time64, fd, msgvec, vlen, flags, |
79a9b408 DG |
25 | timeout ? ((long long[]){s, ns}) : 0); |
26 | if (SYS_recvmmsg == SYS_recvmmsg_time64 || r!=-ENOSYS) | |
27 | return __syscall_ret(r); | |
575e1579 DG |
28 | if (vlen > IOV_MAX) vlen = IOV_MAX; |
29 | socklen_t csize[vlen]; | |
30 | for (int i=0; i<vlen; i++) csize[i] = msgvec[i].msg_hdr.msg_controllen; | |
31 | r = __syscall_cp(SYS_recvmmsg, fd, msgvec, vlen, flags, | |
79a9b408 | 32 | timeout ? ((long[]){CLAMP(s), ns}) : 0); |
575e1579 DG |
33 | for (int i=0; i<r; i++) |
34 | __convert_scm_timestamps(&msgvec[i].msg_hdr, csize[i]); | |
35 | return __syscall_ret(r); | |
79a9b408 | 36 | #else |
320054e8 | 37 | return syscall_cp(SYS_recvmmsg, fd, msgvec, vlen, flags, timeout); |
79a9b408 | 38 | #endif |
320054e8 | 39 | } |