This system call performs the same task as the readv() system call,
with the exception of having the fourth argument, offset, which
specifes the file offset at which the input operation is to be performed.
Because of this, the preadv() implementation is based on the readv()
implementation in linux-user mode.

But, since preadv() is implemented in the kernel as a 5-argument syscall,
5 arguments are needed to be handled as input and passed to the host

The pos_l and pos_h argument of the safe_preadv() are of type unsigned
long, which can be of different sizes on different platforms. The input
arguments are converted to the appropriate host size when passed to

Signed-off-by: Dejan Jovicevic <>
 linux-user/syscall.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 0815f30..048d9fa 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -908,6 +908,8 @@ safe_syscall2(int, tkill, int, tid, int, sig)
 safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
 safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
 safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
+safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
+              unsigned long, pos_l, unsigned long, pos_h)
 safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
               socklen_t, addrlen)
 safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
@@ -9894,6 +9896,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
+#if defined(TARGET_NR_preadv)
+    case TARGET_NR_preadv:
+        {
+            struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
+            if (vec != NULL) {
+                ret = get_errno(safe_preadv(arg1, vec, arg3, arg4, arg5));
+                unlock_iovec(vec, arg2, arg3, 1);
+            } else {
+                ret = -host_to_target_errno(errno);
+           }
+        }
+        break;
     case TARGET_NR_getsid:
         ret = get_errno(getsid(arg1));

Reply via email to