Fixes #815

Signed-off-by: Rick Payne <[email protected]>
---
 fs/vfs/main.cc        | 15 +++++++++++++++
 tests/tst-sendfile.cc | 28 +++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
index 8fecc08..924bfad 100644
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -2039,6 +2039,21 @@ int sendfile(int out_fd, int in_fd, off_t *_offset, 
size_t count)
         offset = lseek(in_fd, 0, SEEK_CUR);
     }
 
+    // Constrain count to the extent of the file...
+    struct stat st;
+    if (fstat(in_fd, &st) < 0) {
+        return -1;
+    } else {
+        if (offset >= st.st_size) {
+            return 0;
+        } else if ((offset + count) >= st.st_size) {
+            count = st.st_size - offset;
+            if (count == 0) {
+                return 0;
+            }
+        }
+    }
+
     size_t bytes_to_mmap = count + (offset % mmu::page_size);
     off_t offset_for_mmap =  align_down(offset, (off_t)mmu::page_size);
 
diff --git a/tests/tst-sendfile.cc b/tests/tst-sendfile.cc
index 2dcb302..0eb800a 100644
--- a/tests/tst-sendfile.cc
+++ b/tests/tst-sendfile.cc
@@ -163,6 +163,22 @@ int test_sendfile_on_socket(off_t *offset, size_t count)
     return listener_result == 0 ? ret : -1;
 }
 
+int test_extents(int testfile_readfd, size_t offset, size_t count)
+{
+    const char *out_file = "testdata_sendfile_output";
+    off_t off;
+    int write_fd = open(out_file, O_RDWR | O_TRUNC | O_CREAT, S_IRWXU);
+    if (write_fd == -1) {
+        printf("\topen() failed with error message = %s\n",strerror(errno));
+        return -1;
+    }
+    lseek(testfile_readfd, 0 , SEEK_CUR);
+    off = offset;
+    int ret  = sendfile(write_fd, testfile_readfd, &off, count);
+    close(write_fd);
+    return ret;
+}
+
 int main()
 {
     int ret;
@@ -200,12 +216,22 @@ int main()
                 report(test_functions[i](offset_p[j], count_array[k]) == 
count_array[k], message.c_str());
             }
             offset = 0;
-           report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to 
beginning of file");
+            report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to 
beginning of file");
             report(test_functions[i](offset_p[j], size_test_file) == 
size_test_file, "copy entire file");
             printf("\n\n");
         }
     }
 
+    // Test extents...
+    report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to beginning 
of file");
+    report(test_extents(testfile_readfd, 0, size_test_file + 1) == 
size_test_file, "file size extent");
+    report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to beginning 
of file");
+    report(test_extents(testfile_readfd, 10, size_test_file) == 
(size_test_file - 10), "file size extent with offset");
+    report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to beginning 
of file");
+    report(test_extents(testfile_readfd, size_test_file - 1, 1) == 1, "file 
size extent with offset (tail)");
+    report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to beginning 
of file");
+    report(test_extents(testfile_readfd, size_test_file, 1) == 0, "file size 
extent with offset (tail, no bytes)");
+
     /* force sendfile to fail in rest of test cases */
     ret = sendfile(100, testfile_readfd, NULL, 10);
     report(ret == -1 && errno == EBADF, "test for bad out_fd");
-- 
2.7.4

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to