From a656c516963a2596da2ce6ecb0066070091578fb Mon Sep 17 00:00:00 2001 From: Rodrigo Oliveira Date: Tue, 27 Oct 2020 17:12:35 -0300 Subject: [PATCH] Add os sendfile function and python test --- extra_tests/snippets/stdlib_os.py | 12 +++++++++ vm/src/stdlib/os.rs | 41 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/extra_tests/snippets/stdlib_os.py b/extra_tests/snippets/stdlib_os.py index 5f312efb8..0ea37775a 100644 --- a/extra_tests/snippets/stdlib_os.py +++ b/extra_tests/snippets/stdlib_os.py @@ -17,6 +17,18 @@ assert_raises(FileNotFoundError, assert_raises(FileNotFoundError, lambda: os.rename('DOES_NOT_EXIST', 'DOES_NOT_EXIST 2')) +src_fd = os.open('README.md', os.O_RDONLY) +dest_fd = os.open('destination.md', os.O_RDWR | os.O_CREAT) +src_len = os.stat('README.md').st_size + +bytes_sent = os.sendfile(dest_fd, src_fd, 0, src_len) +assert src_len == bytes_sent + +os.lseek(dest_fd, 0, 0) +assert os.read(src_fd, src_len) == os.read(dest_fd, bytes_sent) +os.close(src_fd) +os.close(dest_fd) + try: os.open('DOES_NOT_EXIST', 0) except OSError as err: diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 7815c2b87..a961cb625 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -337,6 +337,47 @@ mod _os { Err(vm.new_os_error("os.open not implemented on this platform".to_owned())) } + #[cfg(any(target_os = "linux"))] + #[pyfunction] + pub(crate) fn sendfile( + out_fd: i32, + in_fd: i32, + offset: i64, + count: u64, + vm: &VirtualMachine, + ) -> PyResult { + let mut file_offset = offset; + + let res = + nix::sys::sendfile::sendfile(out_fd, in_fd, Some(&mut file_offset), count as usize) + .map_err(|err| err.into_pyexception(vm))?; + Ok(vm.ctx.new_int(res as u64)) + } + + #[cfg(any(target_os = "macos"))] + #[pyfunction] + pub(crate) fn sendfile( + out_fd: i64, + in_fd: i64, + offset: u64, + count: u64, + headers: OptionalArg, + trailers: OptionalArg, + flags: OptionalArg, + vm: &VirtualMachine, + ) -> PyResult { + let res = nix::sys::sendfile::sendfile( + in_fd, + out_fd, + offset, + Some(count as usize), + headers, + trailers, + ) + .map_err(|err| err.into_pyexception(vm))?; + Ok(vm.ctx.new_int(res as u64)) + } + #[pyfunction] fn error(message: OptionalArg, vm: &VirtualMachine) -> PyResult { let msg = message.map_or("".to_owned(), |msg| msg.borrow_value().to_owned());