diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/recvmsg.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/recvmsg.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/sysdeps/unix/sysv/linux/recvmsg.c b/sysdeps/unix/sysv/linux/recvmsg.c index 4caf22e8bf..25a319358b 100644 --- a/sysdeps/unix/sysv/linux/recvmsg.c +++ b/sysdeps/unix/sysv/linux/recvmsg.c @@ -15,23 +15,43 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <errno.h> -#include <signal.h> #include <sys/socket.h> - #include <sysdep-cancel.h> #include <socketcall.h> -#include <kernel-features.h> -#include <sys/syscall.h> +#include <shlib-compat.h> ssize_t __libc_recvmsg (int fd, struct msghdr *msg, int flags) { + ssize_t ret; + + /* POSIX specifies that both msghdr::msg_iovlen and msghdr::msg_controllen + to be int and socklen_t respectively. However Linux defines it as + both size_t. So for 64-bit it requires some adjustments by copying to + temporary header and zeroing the pad fields. */ +#if __WORDSIZE == 64 + struct msghdr hdr, *orig = msg; + if (msg != NULL) + { + hdr = *msg; + hdr.__glibc_reserved1 = 0; + hdr.__glibc_reserved2 = 0; + msg = &hdr; + } +#endif + #ifdef __ASSUME_RECVMSG_SYSCALL - return SYSCALL_CANCEL (recvmsg, fd, msg, flags); + ret = SYSCALL_CANCEL (recvmsg, fd, msg, flags); #else - return SOCKETCALL_CANCEL (recvmsg, fd, msg, flags); + ret = SOCKETCALL_CANCEL (recvmsg, fd, msg, flags); #endif + +#if __WORDSIZE == 64 + if (orig != NULL) + *orig = hdr; +#endif + + return ret; } -weak_alias (__libc_recvmsg, recvmsg) weak_alias (__libc_recvmsg, __recvmsg) +versioned_symbol (libc, __libc_recvmsg, recvmsg, GLIBC_2_24); |