From a8fd1aba8584cbe68583907ce766fd8ecfe81f4b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 8 Feb 2013 07:31:55 +0000 Subject: [PATCH] linux-user: Implement sendfile and sendfile64 Implement the sendfile and sendfile64 syscalls. This implementation passes all the LTP test cases for these syscalls. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Riku Voipio --- configure | 17 ++++++++++++++ linux-user/syscall.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/configure b/configure index 84317c6826..a416e23597 100755 --- a/configure +++ b/configure @@ -2760,6 +2760,20 @@ if compile_prog "" "" ; then epoll_pwait=yes fi +# check for sendfile support +sendfile=no +cat > $TMPC << EOF +#include + +int main(void) +{ + return sendfile(0, 0, 0, 0); +} +EOF +if compile_prog "" "" ; then + sendfile=yes +fi + # Check if tools are available to build documentation. if test "$docs" != "no" ; then if has makeinfo && has pod2man; then @@ -3628,6 +3642,9 @@ fi if test "$epoll_pwait" = "yes" ; then echo "CONFIG_EPOLL_PWAIT=y" >> $config_host_mak fi +if test "$sendfile" = "yes" ; then + echo "CONFIG_SENDFILE=y" >> $config_host_mak +fi if test "$inotify" = "yes" ; then echo "CONFIG_INOTIFY=y" >> $config_host_mak fi diff --git a/linux-user/syscall.c b/linux-user/syscall.c index bab9ab58a0..77281f1b48 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -78,6 +78,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #ifdef CONFIG_ATTR #include "qemu/xattr.h" #endif +#ifdef CONFIG_SENDFILE +#include +#endif #define termios host_termios #define winsize host_winsize @@ -7531,8 +7534,58 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #else goto unimplemented; #endif + +#ifdef CONFIG_SENDFILE case TARGET_NR_sendfile: + { + off_t *offp = NULL; + off_t off; + if (arg3) { + ret = get_user_sal(off, arg3); + if (is_error(ret)) { + break; + } + offp = &off; + } + ret = get_errno(sendfile(arg1, arg2, offp, arg4)); + if (!is_error(ret) && arg3) { + abi_long ret2 = put_user_sal(off, arg3); + if (is_error(ret2)) { + ret = ret2; + } + } + break; + } +#ifdef TARGET_NR_sendfile64 + case TARGET_NR_sendfile64: + { + off_t *offp = NULL; + off_t off; + if (arg3) { + ret = get_user_s64(off, arg3); + if (is_error(ret)) { + break; + } + offp = &off; + } + ret = get_errno(sendfile(arg1, arg2, offp, arg4)); + if (!is_error(ret) && arg3) { + abi_long ret2 = put_user_s64(off, arg3); + if (is_error(ret2)) { + ret = ret2; + } + } + break; + } +#endif +#else + case TARGET_NR_sendfile: +#ifdef TARGET_NR_sendfile64: + case TARGET_NR_sendfile64: +#endif goto unimplemented; +#endif + #ifdef TARGET_NR_getpmsg case TARGET_NR_getpmsg: goto unimplemented;