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.