mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
host_env: Use Rustix for copy_file_range (#8099)
Rustix bypasses `libc` to make direct syscalls on Linux. Rustix is also semantically cleaner than `libc` itself. For `copy_file_range`, the offsets can't be negative but `libc`'s `off_t` type is an `i64` because it's used elsewhere, including for functions that CAN take a negative offset. Rustix is cleaner because the offsets are `u64`.
This commit is contained in:
1 parent
370fc76f6c
commit
a0fcafd3f5
3 files changed
+28
-27
No files matched your search
+1
-1
@@ -284,7 +284,7 @@ radium = "1.1.1"
|
||||
rand = "0.10"
|
||||
rapidhash = "4.4.1"
|
||||
result-like = "0.5.0"
|
||||
rustix = { version = "1.1", features = ["event", "param", "system"] }
|
||||
rustix = { version = "1.1", features = ["event", "fs", "param", "system"] }
|
||||
rustls = { version = "0.23.39", default-features = false }
|
||||
rustls-graviola = "0.3"
|
||||
rustls-native-certs = "0.8"
|
||||
|
||||
+13
-22
@@ -256,30 +256,14 @@ pub fn system(command: &CStr) -> libc::c_int {
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn copy_file_range(
|
||||
src: crt_fd::Borrowed<'_>,
|
||||
offset_src: Option<&mut crt_fd::Offset>,
|
||||
offset_src: Option<&mut u64>,
|
||||
dst: crt_fd::Borrowed<'_>,
|
||||
offset_dst: Option<&mut crt_fd::Offset>,
|
||||
offset_dst: Option<&mut u64>,
|
||||
count: usize,
|
||||
) -> io::Result<usize> {
|
||||
#[allow(clippy::unnecessary_option_map_or_else)]
|
||||
let p_offset_src = offset_src.map_or_else(core::ptr::null_mut, |x| x as *mut _);
|
||||
#[allow(clippy::unnecessary_option_map_or_else)]
|
||||
let p_offset_dst = offset_dst.map_or_else(core::ptr::null_mut, |x| x as *mut _);
|
||||
|
||||
// Why not use `libc::copy_file_range`: On musl, the libc wrapper may be missing.
|
||||
let ret = unsafe {
|
||||
libc::syscall(
|
||||
libc::SYS_copy_file_range,
|
||||
src.as_raw(),
|
||||
p_offset_src,
|
||||
dst.as_raw(),
|
||||
p_offset_dst,
|
||||
count,
|
||||
0u32,
|
||||
)
|
||||
};
|
||||
|
||||
usize::try_from(ret).map_err(|_| io::Error::last_os_error())
|
||||
) -> rustix::io::Result<usize> {
|
||||
// `copy_file_range` isn't wrapped in every libc (i.e. musl).
|
||||
// However, Rustix is a safe wrapper around the syscall that bypasses libc.
|
||||
rustix::fs::copy_file_range(src, offset_src, dst, offset_dst, count)
|
||||
}
|
||||
|
||||
pub fn rename(
|
||||
@@ -369,6 +353,13 @@ impl ErrorExt for io::Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(not(windows), not(target_arch = "wasm32")))]
|
||||
impl ErrorExt for rustix::io::Errno {
|
||||
fn posix_errno(&self) -> i32 {
|
||||
self.raw_os_error()
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the last error from C runtime library functions (like _dup, _dup2, _fstat, etc.)
|
||||
/// CRT functions set errno, not GetLastError(), so we need to read errno directly.
|
||||
#[cfg(windows)]
|
||||
|
||||
@@ -1709,20 +1709,30 @@ pub(super) mod _os {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[pyfunction]
|
||||
fn copy_file_range(mut args: CopyFileRangeArgs<'_>, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
fn copy_file_range(args: CopyFileRangeArgs<'_>, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
let count: usize = args
|
||||
.count
|
||||
.try_into()
|
||||
.map_err(|_| vm.new_value_error("count should >= 0"))?;
|
||||
let mut offset_src = args
|
||||
.offset_src
|
||||
.map(TryInto::try_into)
|
||||
.transpose()
|
||||
.map_err(|_| vm.new_value_error("offset_src should be >= 0"))?;
|
||||
let mut offset_dst = args
|
||||
.offset_dst
|
||||
.map(TryInto::try_into)
|
||||
.transpose()
|
||||
.map_err(|_| vm.new_value_error("offset_dst should be >= 0"))?;
|
||||
|
||||
crate::host_env::os::copy_file_range(
|
||||
args.src,
|
||||
args.offset_src.as_mut(),
|
||||
offset_src.as_mut(),
|
||||
args.dst,
|
||||
args.offset_dst.as_mut(),
|
||||
offset_dst.as_mut(),
|
||||
count,
|
||||
)
|
||||
.map_err(|_| vm.new_last_errno_error())
|
||||
.map_err(|e| vm.new_errno_error(e.raw_os_error(), e.to_string()).upcast())
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
||||
Reference in new issue
Block a user