diff --git a/Cargo.toml b/Cargo.toml index 29677e90d7..bbdabbaa56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libredox" authors = ["4lDO2 <4lDO2@protonmail.com>", "vasilito "] -version = "0.1.18+rb0.3.2" +version = "0.1.19+rb0.3.2" edition = "2021" license = "MIT" description = "Redox stable ABI" @@ -20,7 +20,7 @@ mkns = ["ioslice"] # src/lib.rs gate the `From` impls between `libredox::error::Error` # and `syscall::Error`; without the feature, those impls are absent # and `?` propagation between the two types fails. Mirroring -# upstream `libredox 0.1.18`'s feature structure. +# upstream `libredox 0.1.19`'s feature structure. redox_syscall = ["dep:redox_syscall"] [dependencies] diff --git a/src/lib.rs b/src/lib.rs index e44376d4ea..f091acdb43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -356,6 +356,16 @@ extern "C" { metadata: *const u64, metadata_len: usize, ) -> RawResult; + fn redox_sys_call_multiple_v0( + fds: *const usize, + fds_len: usize, + payload: *mut u8, + payload_len: usize, + flags: usize, + metadata: *const u64, + metadata_len: usize, + ) -> RawResult; + fn redox_get_socket_token_v0(fd: usize, payload: *mut u8, payload_len: usize) -> RawResult; fn redox_setns_v0(fd: usize) -> RawResult; @@ -518,6 +528,65 @@ pub mod call { use super::*; + #[cfg(feature = "redox_syscall")] + pub trait Call { + unsafe fn raw_call( + &self, + payload: *mut u8, + payload_len: usize, + flags: syscall::CallFlags, + metadata: &[u64], + ) -> Result; + } + + #[cfg(feature = "redox_syscall")] + impl Call for usize { + unsafe fn raw_call( + &self, + payload: *mut u8, + payload_len: usize, + flags: syscall::CallFlags, + metadata: &[u64], + ) -> Result { + Ok(Error::demux(unsafe { + redox_sys_call_v0( + *self, + payload, + payload_len, + flags.bits(), + metadata.as_ptr(), + metadata.len(), + ) + })?) + } + } + + #[cfg(feature = "redox_syscall")] + impl Call for &[usize] { + /// # Errors + /// + /// * `EXDEV` - The file descriptors belong to different schemes. + unsafe fn raw_call( + &self, + payload: *mut u8, + payload_len: usize, + flags: syscall::CallFlags, + metadata: &[u64], + ) -> Result { + Error::demux(unsafe { + redox_sys_call_multiple_v0( + self.as_ptr(), + self.len(), + payload, + payload_len, + flags.bits(), + metadata.as_ptr(), + metadata.len(), + ) + }) + } + } + /// flags and mode are binary compatible with libc #[inline] pub fn open(path: impl AsRef, flags: i32, mode: u16) -> Result { @@ -656,65 +725,72 @@ unsafe { redox_relpathat_v0(raw_fd, fd, buf.as_mut_ptr(), buf.len()) }) unsafe { redox_close_v1(raw_fd) })?; Ok(()) } + #[cfg(feature = "redox_syscall")] #[inline] - pub fn call_ro( - fd: usize, + pub fn call_ro( + fd: T, payload: &mut [u8], flags: syscall::CallFlags, metadata: &[u64], ) -> Result { - Ok(Error::demux(// SAFETY: caller must verify the safety contract for this operation -unsafe { - redox_sys_call_v0( - fd, + if flags.contains(syscall::CallFlags::WRITE) { + return Err(Error::new(syscall::EINVAL)); + } + // SAFETY: payload/metadata are derived from live slices, so the + // pointer/length pairs are valid for the duration of the call, and + // the Call impl supplies a valid fd. + unsafe { + fd.raw_call( payload.as_mut_ptr(), payload.len(), - (flags | syscall::CallFlags::READ).bits(), - metadata.as_ptr(), - metadata.len(), + flags | syscall::CallFlags::READ, + metadata, ) - })?) + } } #[cfg(feature = "redox_syscall")] #[inline] - pub fn call_wo( - fd: usize, + pub fn call_wo( + fd: T, payload: &[u8], flags: syscall::CallFlags, metadata: &[u64], ) -> Result { - Ok(Error::demux(// SAFETY: caller must verify the safety contract for this operation -unsafe { - redox_sys_call_v0( - fd, - payload.as_ptr() as *mut u8, + if flags.contains(syscall::CallFlags::READ) { + return Err(Error::new(syscall::EINVAL)); + } + // SAFETY: payload/metadata are derived from live slices, so the + // pointer/length pairs are valid for the duration of the call, and + // the Call impl supplies a valid fd. + unsafe { + fd.raw_call( + payload.as_ptr().cast_mut(), payload.len(), - (flags | syscall::CallFlags::WRITE).bits(), - metadata.as_ptr(), - metadata.len(), + flags | syscall::CallFlags::WRITE, + metadata, ) - })?) + } } #[cfg(feature = "redox_syscall")] #[inline] - pub fn call_rw( - fd: usize, + pub fn call_rw( + fd: T, payload: &mut [u8], flags: syscall::CallFlags, metadata: &[u64], ) -> Result { - Ok(Error::demux(// SAFETY: caller must verify the safety contract for this operation -unsafe { - redox_sys_call_v0( - fd, + // SAFETY: payload/metadata are derived from live slices, so the + // pointer/length pairs are valid for the duration of the call, and + // the Call impl supplies a valid fd. + unsafe { + fd.raw_call( payload.as_mut_ptr(), payload.len(), - (flags | syscall::CallFlags::READ | syscall::CallFlags::WRITE).bits(), - metadata.as_ptr(), - metadata.len(), + flags | syscall::CallFlags::READ | syscall::CallFlags::WRITE, + metadata, ) - })?) + } } #[inline]