From fe5b9016f515d5e3693478d45a397d3435efd2fd Mon Sep 17 00:00:00 2001 From: Dean Li Date: Sat, 17 Apr 2021 19:12:52 +0800 Subject: [PATCH 1/3] os: Implement copy_file_range Use `libc::copy_file_range` Related to #1175 --- vm/src/stdlib/os.rs | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index b1550e946..d8f3577e0 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1,3 +1,5 @@ +use std::convert::TryFrom; +use std::convert::TryInto; use std::ffi; use std::fs::File; use std::fs::OpenOptions; @@ -1195,6 +1197,50 @@ mod _os { } } + #[derive(FromArgs)] + struct CopyFileRangeArgs { + #[pyarg(positional)] + src: i32, + #[pyarg(positional)] + dst: i32, + #[pyarg(positional)] + count: i64, + #[pyarg(any, default)] + offset_src: Option, + #[pyarg(any, default)] + offset_dst: Option, + } + + #[cfg(unix)] + #[pyfunction] + fn copy_file_range(args: CopyFileRangeArgs, vm: &VirtualMachine) -> PyResult { + let p_offset_src = args.offset_src.as_ref().map_or_else(std::ptr::null, |x| x); + let p_offset_dst = args.offset_dst.as_ref().map_or_else(std::ptr::null, |x| x); + let count: usize = args + .count + .try_into() + .map_err(|_| vm.new_value_error("count should > 0".to_string()))?; + + // The flags argument is provided to allow + // for future extensions and currently must be to 0. + let flags = 0u32; + + // Safety: p_offset_src and p_offset_dst is a unique pointer for offset_src and offset_dst respectively, + // and will only be freed after this function ends. + let ret = unsafe { + libc::copy_file_range( + args.src, + p_offset_src as *mut i64, + args.dst, + p_offset_dst as *mut i64, + count, + flags, + ) + }; + + usize::try_from(ret).map_err(|_| vm.new_os_error("Fail to copy_file_range".to_string())) + } + #[pyfunction] fn strerror(e: i32) -> String { unsafe { ffi::CStr::from_ptr(libc::strerror(e)) } From f8ee3d7434027a578755b1facc1c1fc6ffd118cd Mon Sep 17 00:00:00 2001 From: Dean Li Date: Sat, 17 Apr 2021 21:36:22 +0800 Subject: [PATCH 2/3] os: copy_file_range only support linux --- vm/src/stdlib/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index d8f3577e0..f4a2e58b8 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1211,7 +1211,7 @@ mod _os { offset_dst: Option, } - #[cfg(unix)] + #[cfg(target_os = "linux")] #[pyfunction] fn copy_file_range(args: CopyFileRangeArgs, vm: &VirtualMachine) -> PyResult { let p_offset_src = args.offset_src.as_ref().map_or_else(std::ptr::null, |x| x); From 6fefadeb3956238dcc0be2154e0966722a91886a Mon Sep 17 00:00:00 2001 From: Dean Li Date: Sun, 18 Apr 2021 09:30:42 +0800 Subject: [PATCH 3/3] os: Fix unused warning and propagate errno to user --- vm/src/stdlib/os.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index f4a2e58b8..01a3a2760 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1,5 +1,3 @@ -use std::convert::TryFrom; -use std::convert::TryInto; use std::ffi; use std::fs::File; use std::fs::OpenOptions; @@ -1197,6 +1195,7 @@ mod _os { } } + #[cfg(target_os = "linux")] #[derive(FromArgs)] struct CopyFileRangeArgs { #[pyarg(positional)] @@ -1214,12 +1213,13 @@ mod _os { #[cfg(target_os = "linux")] #[pyfunction] fn copy_file_range(args: CopyFileRangeArgs, vm: &VirtualMachine) -> PyResult { + use std::convert::{TryFrom, TryInto}; let p_offset_src = args.offset_src.as_ref().map_or_else(std::ptr::null, |x| x); let p_offset_dst = args.offset_dst.as_ref().map_or_else(std::ptr::null, |x| x); let count: usize = args .count .try_into() - .map_err(|_| vm.new_value_error("count should > 0".to_string()))?; + .map_err(|_| vm.new_value_error("count should >= 0".to_string()))?; // The flags argument is provided to allow // for future extensions and currently must be to 0. @@ -1238,7 +1238,7 @@ mod _os { ) }; - usize::try_from(ret).map_err(|_| vm.new_os_error("Fail to copy_file_range".to_string())) + usize::try_from(ret).map_err(|_| errno_err(vm)) } #[pyfunction]