]> xenbits.xensource.com Git - qemu-upstream-4.6-testing.git/commitdiff
linux-user: writev Partial Writes
authorTom Musta <tommusta@gmail.com>
Tue, 12 Aug 2014 18:53:43 +0000 (13:53 -0500)
committerRiku Voipio <riku.voipio@linaro.org>
Fri, 22 Aug 2014 12:06:35 +0000 (15:06 +0300)
Although not technically not required by POSIX, the writev system call will
typically write out its buffers individually.  That is, if the first buffer
is written successfully, but the second buffer pointer is invalid, then
the first chuck will be written and its size is returned.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
linux-user/syscall.c

index 1da216e2fb4a06d4af387a67f199e23e50452614..ebdc70e4ca54fb0b8b75395d05513903328f66a4 100644 (file)
@@ -1803,6 +1803,7 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
     abi_ulong total_len, max_len;
     int i;
     int err = 0;
+    bool bad_address = false;
 
     if (count == 0) {
         errno = 0;
@@ -1843,9 +1844,20 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
             vec[i].iov_base = 0;
         } else {
             vec[i].iov_base = lock_user(type, base, len, copy);
+            /* If the first buffer pointer is bad, this is a fault.  But
+             * subsequent bad buffers will result in a partial write; this
+             * is realized by filling the vector with null pointers and
+             * zero lengths. */
             if (!vec[i].iov_base) {
-                err = EFAULT;
-                goto fail;
+                if (i == 0) {
+                    err = EFAULT;
+                    goto fail;
+                } else {
+                    bad_address = true;
+                }
+            }
+            if (bad_address) {
+                len = 0;
             }
             if (len > max_len - total_len) {
                 len = max_len - total_len;