From c7de321fd88e5b65bb95d23e52ef5cf109c9feba Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sat, 28 Oct 2023 14:19:20 -0700 Subject: [PATCH 1/5] Implement the Buffer trait This is for discussion purposes before I go through the codebase and replace the rest of the code. Signed-off-by: John Nunley --- src/buffer.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 95 insertions(+) create mode 100644 src/buffer.rs diff --git a/src/buffer.rs b/src/buffer.rs new file mode 100644 index 000000000..e932ef9d6 --- /dev/null +++ b/src/buffer.rs @@ -0,0 +1,94 @@ +//! Code for handling buffers to write into. + +#![allow(unsafe_code)] + +use core::mem::MaybeUninit; +use core::slice; + +/// A buffer that the system can write into. +pub unsafe trait Buffer: Sized { + /// The result of the process operation. + type Result; + + /// Convert this buffer into a pointer to a buffer and its capacity. + fn as_buffer(&mut self) -> (*mut T, usize); + + /// Convert a finished buffer pointer into its result. + unsafe fn finish(self, len: usize) -> Self::Result; +} + +unsafe impl Buffer for &mut [T] { + type Result = usize; + + #[inline] + fn as_buffer(&mut self) -> (*mut T, usize) { + (self.as_mut_ptr(), self.len()) + } + + #[inline] + unsafe fn finish(self, len: usize) -> Self::Result { + len + } +} + +unsafe impl<'a, T: AnyBitPattern> Buffer for &'a mut [MaybeUninit] { + type Result = (&'a mut [T], &'a mut [MaybeUninit]); + + #[inline] + fn as_buffer(&mut self) -> (*mut T, usize) { + (self.as_mut_ptr().cast(), self.len()) + } + + #[inline] + unsafe fn finish(self, len: usize) -> Self::Result { + let (init, uninit) = self.split_at_mut(len); + + // SAFETY: The user asserts that the slice is now initialized. + let init = slice::from_raw_parts_mut( + init.as_mut_ptr().cast(), + init.len() + ); + + (init, uninit) + } +} + +/// Implements [`Buffer`] around the `Vec` type. +/// +/// This implementation fills the buffer with data and sets the length. +#[cfg(feature = "alloc")] +unsafe impl Buffer for alloc::vec::Vec { + type Result = alloc::vec::Vec; + + #[inline] + fn as_buffer(&mut self) -> (*mut T, usize) { + (self.as_mut_ptr(), self.len()) + } + + #[inline] + unsafe fn finish(mut self, len: usize) -> Self::Result { + self.set_len(len); + self + } +} + +/// Types made up of plain-old-data. +/// +/// # Safety +/// +/// - The OS can write any byte pattern to this structure. +/// - This type does not implement `Drop`. +pub unsafe trait AnyBitPattern {} + +macro_rules! impl_pod { + ($($ty:ty),*) => { + $( + unsafe impl AnyBitPattern for $ty {} + )* + } +} + +impl_pod! { + u8, i8, u16, i16, u32, i32, u64, i64, + usize, isize +} diff --git a/src/lib.rs b/src/lib.rs index 3c232a3a4..719c2bda6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -187,6 +187,7 @@ pub mod fd { } // The public API modules. +pub mod buffer; #[cfg(feature = "event")] #[cfg_attr(doc_cfg, doc(cfg(feature = "event")))] pub mod event; From 2e2417ad219097fb164febbf65bfe1bd8bc483fd Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 29 Oct 2023 15:23:56 -0700 Subject: [PATCH 2/5] Implement Buffer functionality in rustix::io Signed-off-by: John Nunley --- src/backend/libc/io/syscalls.rs | 12 ++++++------ src/backend/linux_raw/io/syscalls.rs | 24 ++++++++++-------------- src/buffer.rs | 19 +++++++++++++++++++ src/io/read_write.rs | 19 ++++++++++++++----- 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/backend/libc/io/syscalls.rs b/src/backend/libc/io/syscalls.rs index 8d5aefadc..e9a0b098c 100644 --- a/src/backend/libc/io/syscalls.rs +++ b/src/backend/libc/io/syscalls.rs @@ -26,12 +26,12 @@ use { crate::io::{IoSlice, IoSliceMut}, }; -pub(crate) fn read(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result { +pub(crate) unsafe fn read(fd: BorrowedFd<'_>, buf: *mut u8, cap: usize) -> io::Result { unsafe { ret_usize(c::read( borrowed_fd(fd), - buf.as_mut_ptr().cast(), - min(buf.len(), READ_LIMIT), + buf.cast(), + min(cap, READ_LIMIT), )) } } @@ -46,8 +46,8 @@ pub(crate) fn write(fd: BorrowedFd<'_>, buf: &[u8]) -> io::Result { } } -pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], offset: u64) -> io::Result { - let len = min(buf.len(), READ_LIMIT); +pub(crate) fn pread(fd: BorrowedFd<'_>, buf: *mut u8, cap: usize, offset: u64) -> io::Result { + let len = min(cap, READ_LIMIT); // Silently cast; we'll get `EINVAL` if the value is negative. let offset = offset as i64; @@ -59,7 +59,7 @@ pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], offset: u64) -> io::Resu unsafe { ret_usize(c::pread( borrowed_fd(fd), - buf.as_mut_ptr().cast(), + buf.cast(), len, offset, )) diff --git a/src/backend/linux_raw/io/syscalls.rs b/src/backend/linux_raw/io/syscalls.rs index d2cbba0c3..82e7ccaaf 100644 --- a/src/backend/linux_raw/io/syscalls.rs +++ b/src/backend/linux_raw/io/syscalls.rs @@ -15,7 +15,7 @@ use crate::backend::conv::loff_t_from_u64; use crate::backend::conv::zero; use crate::backend::conv::{ c_uint, raw_fd, ret, ret_c_int, ret_c_uint, ret_discarded_fd, ret_owned_fd, ret_usize, slice, - slice_mut, + pass_usize }; #[cfg(target_pointer_width = "32")] use crate::backend::conv::{hi, lo}; @@ -29,16 +29,12 @@ use core::cmp; use linux_raw_sys::general::{F_DUPFD_CLOEXEC, F_GETFD, F_SETFD}; #[inline] -pub(crate) fn read(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result { - let (buf_addr_mut, buf_len) = slice_mut(buf); - - unsafe { ret_usize(syscall!(__NR_read, fd, buf_addr_mut, buf_len)) } +pub(crate) unsafe fn read(fd: BorrowedFd<'_>, buf: *mut u8, len: usize) -> io::Result { + unsafe { ret_usize(syscall!(__NR_read, fd, buf, pass_usize(len))) } } #[inline] -pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], pos: u64) -> io::Result { - let (buf_addr_mut, buf_len) = slice_mut(buf); - +pub(crate) unsafe fn pread(fd: BorrowedFd<'_>, buf: *mut u8, cap: usize, pos: u64) -> io::Result { // #[cfg(all( target_pointer_width = "32", @@ -48,8 +44,8 @@ pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], pos: u64) -> io::Result< ret_usize(syscall!( __NR_pread64, fd, - buf_addr_mut, - buf_len, + buf, + pass_usize(cap), zero(), hi(pos), lo(pos) @@ -63,8 +59,8 @@ pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], pos: u64) -> io::Result< ret_usize(syscall!( __NR_pread64, fd, - buf_addr_mut, - buf_len, + buf, + pass_usize(cap), hi(pos), lo(pos) )) @@ -74,8 +70,8 @@ pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], pos: u64) -> io::Result< ret_usize(syscall!( __NR_pread64, fd, - buf_addr_mut, - buf_len, + buf, + pass_usize(cap), loff_t_from_u64(pos) )) } diff --git a/src/buffer.rs b/src/buffer.rs index e932ef9d6..300d07742 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -5,6 +5,25 @@ use core::mem::MaybeUninit; use core::slice; +use crate::io::Result; + +/// Wrap around a buffer and do something with the pointer and length. +/// +/// # Safety +/// +/// The callback `f` must actually write the return value's worth of instances of `T` to the +/// buffer. +#[inline] +pub(crate) unsafe fn with_buffer< + T: AnyBitPattern, + Buf: Buffer, + F: FnOnce(*mut T, usize) -> Result +>(mut buffer: Buf, f: F) -> Result { + let (ptr, cap) = buffer.as_buffer(); + let len = f(ptr, cap)?; + Ok(buffer.finish(len)) +} + /// A buffer that the system can write into. pub unsafe trait Buffer: Sized { /// The result of the process operation. diff --git a/src/io/read_write.rs b/src/io/read_write.rs index fe454adba..6e9177c3e 100644 --- a/src/io/read_write.rs +++ b/src/io/read_write.rs @@ -1,7 +1,10 @@ //! `read` and `write`, optionally positioned, optionally vectored -use crate::{backend, io}; +#![allow(unsafe_code)] + +use crate::{backend, buffer, io}; use backend::fd::AsFd; +use buffer::{Buffer, with_buffer}; // Declare `IoSlice` and `IoSliceMut`. #[cfg(not(windows))] @@ -33,8 +36,11 @@ pub use backend::io::types::ReadWriteFlags; /// [illumos]: https://illumos.org/man/2/read /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/I_002fO-Primitives.html#index-reading-from-a-file-descriptor #[inline] -pub fn read(fd: Fd, buf: &mut [u8]) -> io::Result { - backend::io::syscalls::read(fd.as_fd(), buf) +pub fn read>(fd: Fd, buf: Buf) -> io::Result { + let fd = fd.as_fd(); + unsafe { + with_buffer(buf, |ptr, cap| backend::io::syscalls::read(fd, ptr, cap)) + } } /// `write(fd, buf)`—Writes to a stream. @@ -85,8 +91,11 @@ pub fn write(fd: Fd, buf: &[u8]) -> io::Result { /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pread§ion=2 /// [illumos]: https://illumos.org/man/2/pread #[inline] -pub fn pread(fd: Fd, buf: &mut [u8], offset: u64) -> io::Result { - backend::io::syscalls::pread(fd.as_fd(), buf, offset) +pub fn pread>(fd: Fd, buf: Buf, offset: u64) -> io::Result { + let fd = fd.as_fd(); + unsafe { + with_buffer(buf, |ptr, cap| backend::io::syscalls::pread(fd.as_fd(), ptr, cap, offset)) + } } /// `pwrite(fd, bufs)`—Writes to a file at a given position. From 3731c5374889801113af7dc55eb841ad0b45fdb1 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 29 Oct 2023 15:43:25 -0700 Subject: [PATCH 3/5] Implement Buffer usage in rustix::net Signed-off-by: John Nunley --- src/backend/libc/net/syscalls.rs | 15 ++++++------ src/backend/linux_raw/io/syscalls.rs | 35 ++++++++++++++------------- src/backend/linux_raw/net/syscalls.rs | 33 ++++++++++++------------- src/net/send_recv/mod.rs | 25 +++++++++++++------ 4 files changed, 59 insertions(+), 49 deletions(-) diff --git a/src/backend/libc/net/syscalls.rs b/src/backend/libc/net/syscalls.rs index 75d63e1b3..db3273263 100644 --- a/src/backend/libc/net/syscalls.rs +++ b/src/backend/libc/net/syscalls.rs @@ -31,12 +31,12 @@ use { }; #[cfg(not(any(target_os = "redox", target_os = "wasi")))] -pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io::Result { +pub(crate) unsafe fn recv(fd: BorrowedFd<'_>, buf: *mut u8, cap: usize, flags: RecvFlags) -> io::Result { unsafe { ret_send_recv(c::recv( borrowed_fd(fd), - buf.as_mut_ptr().cast(), - send_recv_len(buf.len()), + buf.cast(), + send_recv_len(cap), bitflags_bits!(flags), )) } @@ -55,9 +55,10 @@ pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Resu } #[cfg(not(any(target_os = "redox", target_os = "wasi")))] -pub(crate) fn recvfrom( +pub(crate) unsafe fn recvfrom( fd: BorrowedFd<'_>, - buf: &mut [u8], + buf: *mut u8, + cap: usize, flags: RecvFlags, ) -> io::Result<(usize, Option)> { unsafe { @@ -71,8 +72,8 @@ pub(crate) fn recvfrom( ret_send_recv(c::recvfrom( borrowed_fd(fd), - buf.as_mut_ptr().cast(), - send_recv_len(buf.len()), + buf.cast(), + send_recv_len(cap), bitflags_bits!(flags), storage.as_mut_ptr().cast(), &mut len, diff --git a/src/backend/linux_raw/io/syscalls.rs b/src/backend/linux_raw/io/syscalls.rs index 82e7ccaaf..f178e4c2a 100644 --- a/src/backend/linux_raw/io/syscalls.rs +++ b/src/backend/linux_raw/io/syscalls.rs @@ -302,25 +302,26 @@ pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> { // Do a `recv` with `PEEK` and `DONTWAIT` for 1 byte. A 0 indicates // the read side is shut down; an `EWOULDBLOCK` indicates the read // side is still open. - // - // TODO: This code would benefit from having a better way to read into - // uninitialized memory. - let mut buf = [0]; - match crate::backend::net::syscalls::recv( - fd, - &mut buf, - RecvFlags::PEEK | RecvFlags::DONTWAIT, - ) { - Ok(0) => read = false, - Err(err) => { - #[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK` - match err { - io::Errno::AGAIN | io::Errno::WOULDBLOCK => (), - io::Errno::NOTSOCK => not_socket = true, - _ => return Err(err), + let mut buf = core::mem::MaybeUninit::::uninit(); + + unsafe { + match crate::backend::net::syscalls::recv( + fd, + buf.as_mut_ptr(), + 1, + RecvFlags::PEEK | RecvFlags::DONTWAIT, + ) { + Ok(0) => read = false, + Err(err) => { + #[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK` + match err { + io::Errno::AGAIN | io::Errno::WOULDBLOCK => (), + io::Errno::NOTSOCK => not_socket = true, + _ => return Err(err), + } } + Ok(_) => (), } - Ok(_) => (), } } if write && !not_socket { diff --git a/src/backend/linux_raw/net/syscalls.rs b/src/backend/linux_raw/net/syscalls.rs index 908cf773f..b82940121 100644 --- a/src/backend/linux_raw/net/syscalls.rs +++ b/src/backend/linux_raw/net/syscalls.rs @@ -13,8 +13,8 @@ use super::send_recv::{RecvFlags, SendFlags}; use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; use crate::backend::c; use crate::backend::conv::{ - by_mut, by_ref, c_int, c_uint, ret, ret_owned_fd, ret_usize, size_of, slice, slice_mut, - socklen_t, zero, + by_mut, by_ref, c_int, c_uint, ret, ret_owned_fd, ret_usize, size_of, slice, + socklen_t, zero, pass_usize, }; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io::{self, IoSlice, IoSliceMut}; @@ -585,9 +585,7 @@ pub(crate) fn sendto_unix( } #[inline] -pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io::Result { - let (buf_addr_mut, buf_len) = slice_mut(buf); - +pub(crate) unsafe fn recv(fd: BorrowedFd<'_>, buf: *mut u8, cap: usize, flags: RecvFlags) -> io::Result { #[cfg(not(any( target_arch = "aarch64", target_arch = "mips64", @@ -597,7 +595,7 @@ pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io:: target_arch = "x86_64", )))] unsafe { - ret_usize(syscall!(__NR_recv, fd, buf_addr_mut, buf_len, flags)) + ret_usize(syscall!(__NR_recv, fd, buf, pass_usize(cap), flags)) } #[cfg(any( target_arch = "aarch64", @@ -610,8 +608,8 @@ pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io:: ret_usize(syscall!( __NR_recvfrom, fd, - buf_addr_mut, - buf_len, + buf, + pass_usize(cap), flags, zero(), zero() @@ -624,8 +622,8 @@ pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io:: x86_sys(SYS_RECV), slice_just_addr::, _>(&[ fd.into(), - buf_addr_mut, - buf_len, + buf, + pass_usize(cap), flags.into(), ]) )) @@ -633,13 +631,12 @@ pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io:: } #[inline] -pub(crate) fn recvfrom( +pub(crate) unsafe fn recvfrom( fd: BorrowedFd<'_>, - buf: &mut [u8], + buf: *mut u8, + cap: usize, flags: RecvFlags, ) -> io::Result<(usize, Option)> { - let (buf_addr_mut, buf_len) = slice_mut(buf); - let mut addrlen = core::mem::size_of::() as socklen_t; let mut storage = MaybeUninit::::uninit(); @@ -653,8 +650,8 @@ pub(crate) fn recvfrom( let nread = ret_usize(syscall!( __NR_recvfrom, fd, - buf_addr_mut, - buf_len, + buf, + pass_usize(cap), flags, &mut storage, by_mut(&mut addrlen) @@ -665,8 +662,8 @@ pub(crate) fn recvfrom( x86_sys(SYS_RECVFROM), slice_just_addr::, _>(&[ fd.into(), - buf_addr_mut, - buf_len, + buf, + pass_usize(cap), flags.into(), (&mut storage).into(), by_mut(&mut addrlen), diff --git a/src/net/send_recv/mod.rs b/src/net/send_recv/mod.rs index a377f65ad..f2b2d2f44 100644 --- a/src/net/send_recv/mod.rs +++ b/src/net/send_recv/mod.rs @@ -1,10 +1,13 @@ //! `recv`, `send`, and variants. +#![allow(unsafe_code)] + #[cfg(unix)] use crate::net::SocketAddrUnix; use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; -use crate::{backend, io}; +use crate::{backend, buffer, io}; use backend::fd::{AsFd, BorrowedFd}; +use buffer::{Buffer, with_buffer}; pub use backend::net::send_recv::{RecvFlags, SendFlags}; @@ -53,8 +56,11 @@ pub use msg::*; /// [illumos]: https://illumos.org/man/3SOCKET/recv /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Data.html #[inline] -pub fn recv(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result { - backend::net::syscalls::recv(fd.as_fd(), buf, flags) +pub fn recv>(fd: Fd, buf: Buf, flags: RecvFlags) -> io::Result { + let fd = fd.as_fd(); + unsafe { + with_buffer(buf, |ptr, cap| backend::net::syscalls::recv(fd.as_fd(), ptr, cap, flags)) + } } /// `send(fd, buf, flags)`—Writes data to a socket. @@ -116,12 +122,17 @@ pub fn send(fd: Fd, buf: &[u8], flags: SendFlags) -> io::Result /// [illumos]: https://illumos.org/man/3SOCKET/recvfrom /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Datagrams.html #[inline] -pub fn recvfrom( +pub fn recvfrom>( fd: Fd, - buf: &mut [u8], + mut buf: Buf, flags: RecvFlags, -) -> io::Result<(usize, Option)> { - backend::net::syscalls::recvfrom(fd.as_fd(), buf, flags) +) -> io::Result<(Buf::Result, Option)> { + let fd = fd.as_fd(); + unsafe { + let (ptr, cap) = buf.as_buffer(); + let (len, addr) = backend::net::syscalls::recvfrom(fd.as_fd(), ptr, cap, flags)?; + Ok((buf.finish(len), addr)) + } } /// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific IP From 5a34b013ecf34f30aa0dd3b741e8cfbaca6abaac Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 29 Oct 2023 15:47:11 -0700 Subject: [PATCH 4/5] Implement Buffer in rand Signed-off-by: John Nunley --- src/backend/libc/rand/syscalls.rs | 4 ++-- src/backend/linux_raw/rand/syscalls.rs | 7 +++---- src/rand/getrandom.rs | 11 ++++++++--- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/backend/libc/rand/syscalls.rs b/src/backend/libc/rand/syscalls.rs index 8a995f2e6..29512fcef 100644 --- a/src/backend/libc/rand/syscalls.rs +++ b/src/backend/libc/rand/syscalls.rs @@ -4,11 +4,11 @@ use {crate::backend::c, crate::backend::conv::ret_usize, crate::io, crate::rand::GetRandomFlags}; #[cfg(linux_kernel)] -pub(crate) fn getrandom(buf: &mut [u8], flags: GetRandomFlags) -> io::Result { +pub(crate) unsafe fn getrandom(buf: *mut u8, cap: usize, flags: GetRandomFlags) -> io::Result { // `getrandom` wasn't supported in glibc until 2.25. weak_or_syscall! { fn getrandom(buf: *mut c::c_void, buflen: c::size_t, flags: c::c_uint) via SYS_getrandom -> c::ssize_t } - unsafe { ret_usize(getrandom(buf.as_mut_ptr().cast(), buf.len(), flags.bits())) } + unsafe { ret_usize(getrandom(buf.cast(), cap, flags.bits())) } } diff --git a/src/backend/linux_raw/rand/syscalls.rs b/src/backend/linux_raw/rand/syscalls.rs index e744f3193..609d7fab8 100644 --- a/src/backend/linux_raw/rand/syscalls.rs +++ b/src/backend/linux_raw/rand/syscalls.rs @@ -5,12 +5,11 @@ //! See the `rustix::backend` module documentation for details. #![allow(unsafe_code, clippy::undocumented_unsafe_blocks)] -use crate::backend::conv::{ret_usize, slice_mut}; +use crate::backend::conv::{ret_usize, pass_usize}; use crate::io; use crate::rand::GetRandomFlags; #[inline] -pub(crate) fn getrandom(buf: &mut [u8], flags: GetRandomFlags) -> io::Result { - let (buf_addr_mut, buf_len) = slice_mut(buf); - unsafe { ret_usize(syscall!(__NR_getrandom, buf_addr_mut, buf_len, flags)) } +pub(crate) fn getrandom(buf: *mut u8, cap: usize, flags: GetRandomFlags) -> io::Result { + unsafe { ret_usize(syscall!(__NR_getrandom, buf, pass_usize(cap), flags)) } } diff --git a/src/rand/getrandom.rs b/src/rand/getrandom.rs index 3fed0dd08..4abca14ea 100644 --- a/src/rand/getrandom.rs +++ b/src/rand/getrandom.rs @@ -1,4 +1,7 @@ -use crate::{backend, io}; +#![allow(unsafe_code)] + +use crate::{backend, buffer, io}; +use buffer::{Buffer, with_buffer}; pub use backend::rand::types::GetRandomFlags; @@ -15,6 +18,8 @@ pub use backend::rand::types::GetRandomFlags; /// /// [Linux]: https://man7.org/linux/man-pages/man2/getrandom.2.html #[inline] -pub fn getrandom(buf: &mut [u8], flags: GetRandomFlags) -> io::Result { - backend::rand::syscalls::getrandom(buf, flags) +pub fn getrandom>(buf: Buf, flags: GetRandomFlags) -> io::Result { + unsafe { + with_buffer(buf, |ptr, cap| backend::rand::syscalls::getrandom(ptr, cap, flags)) + } } From 7697e6c0b8d74ec1ad9458c87edb7034eef2675a Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sun, 29 Oct 2023 15:56:11 -0700 Subject: [PATCH 5/5] Implement Buffer for fs Signed-off-by: John Nunley --- src/backend/libc/fs/syscalls.rs | 24 +++++++------------ src/backend/linux_raw/fs/syscalls.rs | 26 ++++++++++----------- src/fs/xattr.rs | 35 +++++++++++++++++----------- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index 72034ae55..382283edc 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -2213,16 +2213,14 @@ struct Attrlist { } #[cfg(any(apple, linux_kernel))] -pub(crate) fn getxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result { - let value_ptr = value.as_mut_ptr(); - +pub(crate) unsafe fn getxattr(path: &CStr, name: &CStr, value_ptr: *mut u8, cap: usize) -> io::Result { #[cfg(not(apple))] unsafe { ret_usize(c::getxattr( path.as_ptr(), name.as_ptr(), value_ptr.cast::(), - value.len(), + cap, )) } @@ -2232,7 +2230,7 @@ pub(crate) fn getxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result path.as_ptr(), name.as_ptr(), value_ptr.cast::(), - value.len(), + cap, 0, 0, )) @@ -2240,16 +2238,14 @@ pub(crate) fn getxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result } #[cfg(any(apple, linux_kernel))] -pub(crate) fn lgetxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result { - let value_ptr = value.as_mut_ptr(); - +pub(crate) unsafe fn lgetxattr(path: &CStr, name: &CStr, value_ptr: *mut u8, cap: usize) -> io::Result { #[cfg(not(apple))] unsafe { ret_usize(c::lgetxattr( path.as_ptr(), name.as_ptr(), value_ptr.cast::(), - value.len(), + cap, )) } @@ -2259,7 +2255,7 @@ pub(crate) fn lgetxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Resul path.as_ptr(), name.as_ptr(), value_ptr.cast::(), - value.len(), + cap, 0, c::XATTR_NOFOLLOW, )) @@ -2267,16 +2263,14 @@ pub(crate) fn lgetxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Resul } #[cfg(any(apple, linux_kernel))] -pub(crate) fn fgetxattr(fd: BorrowedFd<'_>, name: &CStr, value: &mut [u8]) -> io::Result { - let value_ptr = value.as_mut_ptr(); - +pub(crate) unsafe fn fgetxattr(fd: BorrowedFd<'_>, name: &CStr, value_ptr: *mut u8, cap: usize) -> io::Result { #[cfg(not(apple))] unsafe { ret_usize(c::fgetxattr( borrowed_fd(fd), name.as_ptr(), value_ptr.cast::(), - value.len(), + cap, )) } @@ -2286,7 +2280,7 @@ pub(crate) fn fgetxattr(fd: BorrowedFd<'_>, name: &CStr, value: &mut [u8]) -> io borrowed_fd(fd), name.as_ptr(), value_ptr.cast::(), - value.len(), + cap, 0, 0, )) diff --git a/src/backend/linux_raw/fs/syscalls.rs b/src/backend/linux_raw/fs/syscalls.rs index f856fa8b0..df2325c3a 100644 --- a/src/backend/linux_raw/fs/syscalls.rs +++ b/src/backend/linux_raw/fs/syscalls.rs @@ -9,8 +9,9 @@ use crate::backend::c; use crate::backend::conv::fs::oflags_for_open_how; use crate::backend::conv::{ - by_ref, c_int, c_uint, dev_t, opt_mut, pass_usize, raw_fd, ret, ret_c_int, ret_c_uint, - ret_infallible, ret_owned_fd, ret_usize, size_of, slice, slice_mut, zero, + by_ref, c_int, c_uint, dev_t, opt_mut, raw_fd, ret, ret_c_int, ret_c_uint, + ret_infallible, ret_owned_fd, ret_usize, size_of, slice, pass_usize, zero, + slice_mut }; #[cfg(target_pointer_width = "64")] use crate::backend::conv::{loff_t, loff_t_from_u64, ret_u64}; @@ -1518,43 +1519,40 @@ pub(crate) fn inotify_rm_watch(infd: BorrowedFd<'_>, wfd: i32) -> io::Result<()> } #[inline] -pub(crate) fn getxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result { - let (value_addr_mut, value_len) = slice_mut(value); +pub(crate) unsafe fn getxattr(path: &CStr, name: &CStr, value: *mut u8, cap: usize) -> io::Result { unsafe { ret_usize(syscall!( __NR_getxattr, path, name, - value_addr_mut, - value_len + value, + pass_usize(cap) )) } } #[inline] -pub(crate) fn lgetxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result { - let (value_addr_mut, value_len) = slice_mut(value); +pub(crate) unsafe fn lgetxattr(path: &CStr, name: &CStr, value: *mut u8, cap: usize) -> io::Result { unsafe { ret_usize(syscall!( __NR_lgetxattr, path, name, - value_addr_mut, - value_len + value, + pass_usize(cap) )) } } #[inline] -pub(crate) fn fgetxattr(fd: BorrowedFd<'_>, name: &CStr, value: &mut [u8]) -> io::Result { - let (value_addr_mut, value_len) = slice_mut(value); +pub(crate) unsafe fn fgetxattr(fd: BorrowedFd<'_>, name: &CStr, value: *mut u8, cap: usize) -> io::Result { unsafe { ret_usize(syscall!( __NR_fgetxattr, fd, name, - value_addr_mut, - value_len + value, + pass_usize(cap) )) } } diff --git a/src/fs/xattr.rs b/src/fs/xattr.rs index 53612f71f..e28fd3bb4 100644 --- a/src/fs/xattr.rs +++ b/src/fs/xattr.rs @@ -1,6 +1,9 @@ -use crate::{backend, io, path}; +#![allow(unsafe_code)] + +use crate::{backend, buffer, io, path}; use backend::c; use backend::fd::AsFd; +use buffer::{Buffer, with_buffer}; use bitflags::bitflags; bitflags! { @@ -28,13 +31,15 @@ bitflags! { /// /// [Linux]: https://man7.org/linux/man-pages/man2/getxattr.2.html #[inline] -pub fn getxattr( +pub fn getxattr>( path: P, name: Name, - value: &mut [u8], -) -> io::Result { + value: Buf, +) -> io::Result { path.into_with_c_str(|path| { - name.into_with_c_str(|name| backend::fs::syscalls::getxattr(path, name, value)) + name.into_with_c_str(|name| unsafe { + with_buffer(value, |ptr, cap| backend::fs::syscalls::getxattr(path, name, ptr, cap)) + }) }) } @@ -47,13 +52,15 @@ pub fn getxattr( /// /// [Linux]: https://man7.org/linux/man-pages/man2/lgetxattr.2.html #[inline] -pub fn lgetxattr( +pub fn lgetxattr>( path: P, name: Name, - value: &mut [u8], -) -> io::Result { + value: Buf, +) -> io::Result { path.into_with_c_str(|path| { - name.into_with_c_str(|name| backend::fs::syscalls::lgetxattr(path, name, value)) + name.into_with_c_str(|name| unsafe { + with_buffer(value, |ptr, cap| backend::fs::syscalls::lgetxattr(path, name, ptr, cap)) + }) }) } @@ -65,12 +72,14 @@ pub fn lgetxattr( /// /// [Linux]: https://man7.org/linux/man-pages/man2/fgetxattr.2.html #[inline] -pub fn fgetxattr( +pub fn fgetxattr>( fd: Fd, name: Name, - value: &mut [u8], -) -> io::Result { - name.into_with_c_str(|name| backend::fs::syscalls::fgetxattr(fd.as_fd(), name, value)) + value: Buf, +) -> io::Result { + name.into_with_c_str(|name| unsafe { + with_buffer(value, |ptr, cap| backend::fs::syscalls::fgetxattr(fd.as_fd(), name, ptr, cap)) + }) } /// `setxattr(path, name, value.as_ptr(), value.len(), flags)`—Set extended