diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e3e2974c0..6c4847c7da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,6 +91,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). ignoring failures from libc. And getters on the `UtsName` struct now return an `&OsStr` instead of `&str`. (#[1672](https://github.com/nix-rust/nix/pull/1672)) +- Replaced `IoVec` with `IoSlice` and `IoSliceMut`, and replaced `IoVec::from_slice` with + `IoSlice::new`. (#[1643](https://github.com/nix-rust/nix/pull/1643)) ### Fixed diff --git a/src/fcntl.rs b/src/fcntl.rs index 6c713608ee..fa64c8eaed 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -629,7 +629,7 @@ pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Resu #[cfg(any(target_os = "linux", target_os = "android"))] pub fn vmsplice( fd: RawFd, - iov: &[crate::sys::uio::IoVec<&[u8]>], + iov: &[std::io::IoSlice<'_>], flags: SpliceFFlags ) -> Result { diff --git a/src/mount/bsd.rs b/src/mount/bsd.rs index ba0c1a2883..b4d611ee39 100644 --- a/src/mount/bsd.rs +++ b/src/mount/bsd.rs @@ -3,7 +3,6 @@ use crate::{ Errno, NixPath, Result, - sys::uio::IoVec }; use libc::{c_char, c_int, c_uint, c_void}; use std::{ @@ -11,7 +10,7 @@ use std::{ ffi::{CString, CStr}, fmt, io, - ptr + marker::PhantomData, }; @@ -198,13 +197,45 @@ pub type NmountResult = std::result::Result<(), NmountError>; #[cfg_attr(docsrs, doc(cfg(all())))] #[derive(Debug, Default)] pub struct Nmount<'a>{ - iov: Vec>, + // n.b. notgull: In reality, this is a list that contains + // both mutable and immutable pointers. + // Be careful using this. + iov: Vec, is_owned: Vec, + marker: PhantomData<&'a ()>, } #[cfg(target_os = "freebsd")] #[cfg_attr(docsrs, doc(cfg(all())))] impl<'a> Nmount<'a> { + /// Helper function to push a slice onto the `iov` array. + fn push_slice(&mut self, val: &'a [u8], is_owned: bool) { + self.iov.push(libc::iovec { + iov_base: val.as_ptr() as *mut _, + iov_len: val.len(), + }); + self.is_owned.push(is_owned); + } + + /// Helper function to push a pointer and its length onto the `iov` array. + fn push_pointer_and_length(&mut self, val: *const u8, len: usize, is_owned: bool) { + self.iov.push(libc::iovec { + iov_base: val as *mut _, + iov_len: len, + }); + self.is_owned.push(is_owned); + } + + /// Helper function to push a `nix` path as owned. + fn push_nix_path(&mut self, val: &P) { + val.with_nix_path(|s| { + let len = s.to_bytes_with_nul().len(); + let ptr = s.to_owned().into_raw() as *const u8; + + self.push_pointer_and_length(ptr, len, true); + }).unwrap(); + } + /// Add an opaque mount option. /// /// Some file systems take binary-valued mount options. They can be set @@ -239,10 +270,8 @@ impl<'a> Nmount<'a> { len: usize ) -> &mut Self { - self.iov.push(IoVec::from_slice(name.to_bytes_with_nul())); - self.is_owned.push(false); - self.iov.push(IoVec::from_raw_parts(val, len)); - self.is_owned.push(false); + self.push_slice(name.to_bytes_with_nul(), false); + self.push_pointer_and_length(val.cast(), len, false); self } @@ -258,10 +287,8 @@ impl<'a> Nmount<'a> { /// .null_opt(&read_only); /// ``` pub fn null_opt(&mut self, name: &'a CStr) -> &mut Self { - self.iov.push(IoVec::from_slice(name.to_bytes_with_nul())); - self.is_owned.push(false); - self.iov.push(IoVec::from_raw_parts(ptr::null_mut(), 0)); - self.is_owned.push(false); + self.push_slice(name.to_bytes_with_nul(), false); + self.push_slice(&[], false); self } @@ -283,17 +310,8 @@ impl<'a> Nmount<'a> { /// ``` pub fn null_opt_owned(&mut self, name: &P) -> &mut Self { - name.with_nix_path(|s| { - let len = s.to_bytes_with_nul().len(); - self.iov.push(IoVec::from_raw_parts( - // Must free it later - s.to_owned().into_raw() as *mut c_void, - len - )); - self.is_owned.push(true); - }).unwrap(); - self.iov.push(IoVec::from_raw_parts(ptr::null_mut(), 0)); - self.is_owned.push(false); + self.push_nix_path(name); + self.push_slice(&[], false); self } @@ -315,10 +333,8 @@ impl<'a> Nmount<'a> { val: &'a CStr ) -> &mut Self { - self.iov.push(IoVec::from_slice(name.to_bytes_with_nul())); - self.is_owned.push(false); - self.iov.push(IoVec::from_slice(val.to_bytes_with_nul())); - self.is_owned.push(false); + self.push_slice(name.to_bytes_with_nul(), false); + self.push_slice(val.to_bytes_with_nul(), false); self } @@ -341,24 +357,8 @@ impl<'a> Nmount<'a> { where P1: ?Sized + NixPath, P2: ?Sized + NixPath { - name.with_nix_path(|s| { - let len = s.to_bytes_with_nul().len(); - self.iov.push(IoVec::from_raw_parts( - // Must free it later - s.to_owned().into_raw() as *mut c_void, - len - )); - self.is_owned.push(true); - }).unwrap(); - val.with_nix_path(|s| { - let len = s.to_bytes_with_nul().len(); - self.iov.push(IoVec::from_raw_parts( - // Must free it later - s.to_owned().into_raw() as *mut c_void, - len - )); - self.is_owned.push(true); - }).unwrap(); + self.push_nix_path(name); + self.push_nix_path(val); self } @@ -369,18 +369,19 @@ impl<'a> Nmount<'a> { /// Actually mount the file system. pub fn nmount(&mut self, flags: MntFlags) -> NmountResult { - // nmount can return extra error information via a "errmsg" return - // argument. const ERRMSG_NAME: &[u8] = b"errmsg\0"; let mut errmsg = vec![0u8; 255]; - self.iov.push(IoVec::from_raw_parts( - ERRMSG_NAME.as_ptr() as *mut c_void, - ERRMSG_NAME.len() - )); - self.iov.push(IoVec::from_raw_parts( - errmsg.as_mut_ptr() as *mut c_void, - errmsg.len() - )); + + // nmount can return extra error information via a "errmsg" return + // argument. + self.push_slice(ERRMSG_NAME, false); + + // SAFETY: we are pushing a mutable iovec here, so we can't use + // the above method + self.iov.push(libc::iovec { + iov_base: errmsg.as_mut_ptr() as *mut c_void, + iov_len: errmsg.len(), + }); let niov = self.iov.len() as c_uint; let iovp = self.iov.as_mut_ptr() as *mut libc::iovec; @@ -412,7 +413,7 @@ impl<'a> Drop for Nmount<'a> { // Free the owned string. Safe because we recorded ownership, // and Nmount does not implement Clone. unsafe { - drop(CString::from_raw(iov.0.iov_base as *mut c_char)); + drop(CString::from_raw(iov.iov_base as *mut c_char)); } } } diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs index 5ec0b52679..2ebcdf4889 100644 --- a/src/sys/sendfile.rs +++ b/src/sys/sendfile.rs @@ -68,13 +68,13 @@ cfg_if! { target_os = "freebsd", target_os = "ios", target_os = "macos"))] { - use crate::sys::uio::IoVec; + use std::io::IoSlice; - #[derive(Clone, Debug, Eq, Hash, PartialEq)] + #[derive(Clone, Debug)] struct SendfileHeaderTrailer<'a>( libc::sf_hdtr, - Option>>, - Option>>, + Option>>, + Option>>, ); impl<'a> SendfileHeaderTrailer<'a> { @@ -82,10 +82,10 @@ cfg_if! { headers: Option<&'a [&'a [u8]]>, trailers: Option<&'a [&'a [u8]]> ) -> SendfileHeaderTrailer<'a> { - let header_iovecs: Option>> = - headers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect()); - let trailer_iovecs: Option>> = - trailers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect()); + let header_iovecs: Option>> = + headers.map(|s| s.iter().map(|b| IoSlice::new(b)).collect()); + let trailer_iovecs: Option>> = + trailers.map(|s| s.iter().map(|b| IoSlice::new(b)).collect()); SendfileHeaderTrailer( libc::sf_hdtr { headers: { diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 8dac6eda32..c661389200 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -14,10 +14,8 @@ use std::net; #[cfg(feature = "uio")] use crate::sys::time::TimeSpec; #[cfg(feature = "uio")] -use crate::sys::{ - time::TimeVal, - uio::IoVec -}; +use crate::sys::time::TimeVal; +use std::io::{IoSlice, IoSliceMut}; #[deny(missing_docs)] mod addr; @@ -657,8 +655,8 @@ pub enum ControlMessageOwned { /// ``` /// # #[macro_use] extern crate nix; /// # use nix::sys::socket::*; - /// # use nix::sys::uio::IoVec; /// # use nix::sys::time::*; + /// # use std::io::{IoSlice, IoSliceMut}; /// # use std::time::*; /// # use std::str::FromStr; /// # fn main() { @@ -676,15 +674,15 @@ pub enum ControlMessageOwned { /// // Get initial time /// let time0 = SystemTime::now(); /// // Send the message - /// let iov = [IoVec::from_slice(message)]; + /// let iov = [IoSlice::new(message)]; /// let flags = MsgFlags::empty(); /// let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap(); /// assert_eq!(message.len(), l); /// // Receive the message /// let mut buffer = vec![0u8; message.len()]; /// let mut cmsgspace = cmsg_space!(TimeVal); - /// let iov = [IoVec::from_mut_slice(&mut buffer)]; - /// let r = recvmsg::(in_socket, &iov, Some(&mut cmsgspace), flags) + /// let mut iov = [IoSliceMut::new(&mut buffer)]; + /// let r = recvmsg::(in_socket, &mut iov, Some(&mut cmsgspace), flags) /// .unwrap(); /// let rtime = match r.cmsgs().next() { /// Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime, @@ -1367,13 +1365,13 @@ impl<'a> ControlMessage<'a> { /// ``` /// # use nix::sys::socket::*; /// # use nix::unistd::pipe; -/// # use nix::sys::uio::IoVec; +/// # use std::io::IoSlice; /// let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, /// SockFlag::empty()) /// .unwrap(); /// let (r, w) = pipe().unwrap(); /// -/// let iov = [IoVec::from_slice(b"hello")]; +/// let iov = [IoSlice::new(b"hello")]; /// let fds = [r]; /// let cmsg = ControlMessage::ScmRights(&fds); /// sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(); @@ -1382,19 +1380,19 @@ impl<'a> ControlMessage<'a> { /// ``` /// # use nix::sys::socket::*; /// # use nix::unistd::pipe; -/// # use nix::sys::uio::IoVec; +/// # use std::io::IoSlice; /// # use std::str::FromStr; /// let localhost = SockaddrIn::from_str("1.2.3.4:8080").unwrap(); /// let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), /// None).unwrap(); /// let (r, w) = pipe().unwrap(); /// -/// let iov = [IoVec::from_slice(b"hello")]; +/// let iov = [IoSlice::new(b"hello")]; /// let fds = [r]; /// let cmsg = ControlMessage::ScmRights(&fds); /// sendmsg(fd, &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap(); /// ``` -pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage], +pub fn sendmsg(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage], flags: MsgFlags, addr: Option<&S>) -> Result where S: SockaddrLike { @@ -1420,7 +1418,7 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage], #[derive(Debug)] pub struct SendMmsgData<'a, I, C, S> where - I: AsRef<[IoVec<&'a [u8]>]>, + I: AsRef<[IoSlice<'a>]>, C: AsRef<[ControlMessage<'a>]>, S: SockaddrLike + 'a { @@ -1459,7 +1457,7 @@ pub fn sendmmsg<'a, I, C, S>( flags: MsgFlags ) -> Result> where - I: AsRef<[IoVec<&'a [u8]>]> + 'a, + I: AsRef<[IoSlice<'a>]> + 'a, C: AsRef<[ControlMessage<'a>]> + 'a, S: SockaddrLike + 'a { @@ -1510,7 +1508,7 @@ pub fn sendmmsg<'a, I, C, S>( #[derive(Debug)] pub struct RecvMmsgData<'a, I> where - I: AsRef<[IoVec<&'a mut [u8]>]> + 'a, + I: AsRef<[IoSliceMut<'a>]> + 'a, { pub iov: I, pub cmsg_buffer: Option<&'a mut Vec>, @@ -1557,7 +1555,7 @@ pub fn recvmmsg<'a, I, S>( timeout: Option ) -> Result>> where - I: AsRef<[IoVec<&'a mut [u8]>]> + 'a, + I: AsRef<[IoSliceMut<'a>]> + 'a, S: Copy + SockaddrLike + 'a { let iter = data.into_iter(); @@ -1653,14 +1651,14 @@ unsafe fn read_mhdr<'a, 'b, S>( } } -unsafe fn pack_mhdr_to_receive<'a, I, S>( +unsafe fn pack_mhdr_to_receive<'outer, 'inner, I, S>( iov: I, cmsg_buffer: &mut Option<&mut Vec>, address: *mut S, ) -> (usize, msghdr) where - I: AsRef<[IoVec<&'a mut [u8]>]> + 'a, - S: SockaddrLike + 'a + I: AsRef<[IoSliceMut<'inner>]> + 'outer, + S: SockaddrLike + 'outer { let (msg_control, msg_controllen) = cmsg_buffer.as_mut() .map(|v| (v.as_mut_ptr(), v.capacity())) @@ -1691,7 +1689,7 @@ fn pack_mhdr_to_send<'a, I, C, S>( addr: Option<&S> ) -> msghdr where - I: AsRef<[IoVec<&'a [u8]>]>, + I: AsRef<[IoSlice<'a>]>, C: AsRef<[ControlMessage<'a>]>, S: SockaddrLike + 'a { @@ -1751,7 +1749,7 @@ fn pack_mhdr_to_send<'a, I, C, S>( /// /// # References /// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html) -pub fn recvmsg<'a, S>(fd: RawFd, iov: &[IoVec<&mut [u8]>], +pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'inner>], mut cmsg_buffer: Option<&'a mut Vec>, flags: MsgFlags) -> Result> where S: SockaddrLike + 'a @@ -1759,7 +1757,7 @@ pub fn recvmsg<'a, S>(fd: RawFd, iov: &[IoVec<&mut [u8]>], let mut address = mem::MaybeUninit::uninit(); let (msg_controllen, mut mhdr) = unsafe { - pack_mhdr_to_receive(&iov, &mut cmsg_buffer, address.as_mut_ptr()) + pack_mhdr_to_receive::<_, S>(iov, &mut cmsg_buffer, address.as_mut_ptr()) }; let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) }; diff --git a/src/sys/uio.rs b/src/sys/uio.rs index 4229830050..ba6c64ef26 100644 --- a/src/sys/uio.rs +++ b/src/sys/uio.rs @@ -3,13 +3,21 @@ use crate::Result; use crate::errno::Errno; use libc::{self, c_int, c_void, size_t, off_t}; +use std::io::{IoSlice, IoSliceMut}; use std::marker::PhantomData; use std::os::unix::io::RawFd; /// Low-level vectored write to a raw file descriptor /// /// See also [writev(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html) -pub fn writev(fd: RawFd, iov: &[IoVec<&[u8]>]) -> Result { +pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result { + // SAFETY: to quote the documentation for `IoSlice`: + // + // [IoSlice] is semantically a wrapper around a &[u8], but is + // guaranteed to be ABI compatible with the iovec type on Unix + // platforms. + // + // Because it is ABI compatible, a pointer cast here is valid let res = unsafe { libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) }; Errno::result(res).map(|r| r as usize) @@ -18,7 +26,8 @@ pub fn writev(fd: RawFd, iov: &[IoVec<&[u8]>]) -> Result { /// Low-level vectored read from a raw file descriptor /// /// See also [readv(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html) -pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result { +pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result { + // SAFETY: same as in writev(), IoSliceMut is ABI-compatible with iovec let res = unsafe { libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) }; Errno::result(res).map(|r| r as usize) @@ -32,10 +41,13 @@ pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result { /// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html) #[cfg(not(target_os = "redox"))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>], +pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>], offset: off_t) -> Result { + #[cfg(target_env = "uclibc")] let offset = offset as libc::off64_t; // uclibc doesn't use off_t + + // SAFETY: same as in writev() let res = unsafe { libc::pwritev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset) }; @@ -52,10 +64,12 @@ pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>], /// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html) #[cfg(not(target_os = "redox"))] #[cfg_attr(docsrs, doc(cfg(all())))] -pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>], +pub fn preadv(fd: RawFd, iov: &mut [IoSliceMut<'_>], offset: off_t) -> Result { #[cfg(target_env = "uclibc")] let offset = offset as libc::off64_t; // uclibc doesn't use off_t + + // SAFETY: same as in readv() let res = unsafe { libc::preadv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset) }; @@ -92,9 +106,9 @@ pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result{ /// A slice of memory in a remote process, starting at address `base` /// and consisting of `len` bytes. /// -/// This is the same underlying C structure as [`IoVec`](struct.IoVec.html), +/// This is the same underlying C structure as `IoSlice`, /// except that it refers to memory in some other process, and is -/// therefore not represented in Rust by an actual slice as `IoVec` is. It +/// therefore not represented in Rust by an actual slice as `IoSlice` is. It /// is used with [`process_vm_readv`](fn.process_vm_readv.html) /// and [`process_vm_writev`](fn.process_vm_writev.html). #[cfg(any(target_os = "linux", target_os = "android"))] @@ -108,13 +122,82 @@ pub struct RemoteIoVec { pub len: usize, } +/// A vector of buffers. +/// +/// Vectored I/O methods like [`writev`] and [`readv`] use this structure for +/// both reading and writing. Each `IoVec` specifies the base address and +/// length of an area in memory. +#[deprecated( + since = "0.24.0", + note = "`IoVec` is no longer used in the public interface, use `IoSlice` or `IoSliceMut` instead" +)] +#[repr(transparent)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub struct IoVec(pub(crate) libc::iovec, PhantomData); + +#[allow(deprecated)] +impl IoVec { + /// View the `IoVec` as a Rust slice. + #[deprecated( + since = "0.24.0", + note = "Use the `Deref` impl of `IoSlice` or `IoSliceMut` instead" + )] + #[inline] + pub fn as_slice(&self) -> &[u8] { + use std::slice; + + unsafe { + slice::from_raw_parts( + self.0.iov_base as *const u8, + self.0.iov_len as usize) + } + } +} + +#[allow(deprecated)] +impl<'a> IoVec<&'a [u8]> { + /// Create an `IoVec` from a Rust slice. + #[deprecated( + since = "0.24.0", + note = "Use `IoSlice::new` instead" + )] + pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> { + IoVec(libc::iovec { + iov_base: buf.as_ptr() as *mut c_void, + iov_len: buf.len() as size_t, + }, PhantomData) + } +} + +#[allow(deprecated)] +impl<'a> IoVec<&'a mut [u8]> { + /// Create an `IoVec` from a mutable Rust slice. + #[deprecated( + since = "0.24.0", + note = "Use `IoSliceMut::new` instead" + )] + pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> { + IoVec(libc::iovec { + iov_base: buf.as_ptr() as *mut c_void, + iov_len: buf.len() as size_t, + }, PhantomData) + } +} + +// The only reason IoVec isn't automatically Send+Sync is because libc::iovec +// contains raw pointers. +#[allow(deprecated)] +unsafe impl Send for IoVec where T: Send {} +#[allow(deprecated)] +unsafe impl Sync for IoVec where T: Sync {} + feature! { #![feature = "process"] /// Write data directly to another process's virtual memory /// (see [`process_vm_writev`(2)]). /// -/// `local_iov` is a list of [`IoVec`]s containing the data to be written, +/// `local_iov` is a list of [`IoSlice`]s containing the data to be written, /// and `remote_iov` is a list of [`RemoteIoVec`]s identifying where the /// data should be written in the target process. On success, returns the /// number of bytes written, which will always be a whole @@ -129,12 +212,12 @@ feature! { /// /// [`process_vm_writev`(2)]: https://man7.org/linux/man-pages/man2/process_vm_writev.2.html /// [ptrace]: ../ptrace/index.html -/// [`IoVec`]: struct.IoVec.html +/// [`IoSlice`]: https://doc.rust-lang.org/std/io/struct.IoSlice.html /// [`RemoteIoVec`]: struct.RemoteIoVec.html #[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] pub fn process_vm_writev( pid: crate::unistd::Pid, - local_iov: &[IoVec<&[u8]>], + local_iov: &[IoSlice<'_>], remote_iov: &[RemoteIoVec]) -> Result { let res = unsafe { @@ -149,7 +232,7 @@ pub fn process_vm_writev( /// Read data directly from another process's virtual memory /// (see [`process_vm_readv`(2)]). /// -/// `local_iov` is a list of [`IoVec`]s containing the buffer to copy +/// `local_iov` is a list of [`IoSliceMut`]s containing the buffer to copy /// data into, and `remote_iov` is a list of [`RemoteIoVec`]s identifying /// where the source data is in the target process. On success, /// returns the number of bytes written, which will always be a whole @@ -164,12 +247,12 @@ pub fn process_vm_writev( /// /// [`process_vm_readv`(2)]: https://man7.org/linux/man-pages/man2/process_vm_readv.2.html /// [`ptrace`]: ../ptrace/index.html -/// [`IoVec`]: struct.IoVec.html +/// [`IoSliceMut`]: https://doc.rust-lang.org/std/io/struct.IoSliceMut.html /// [`RemoteIoVec`]: struct.RemoteIoVec.html #[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] pub fn process_vm_readv( pid: crate::unistd::Pid, - local_iov: &[IoVec<&mut [u8]>], + local_iov: &mut [IoSliceMut<'_>], remote_iov: &[RemoteIoVec]) -> Result { let res = unsafe { @@ -181,59 +264,3 @@ pub fn process_vm_readv( Errno::result(res).map(|r| r as usize) } } - -/// A vector of buffers. -/// -/// Vectored I/O methods like [`writev`] and [`readv`] use this structure for -/// both reading and writing. Each `IoVec` specifies the base address and -/// length of an area in memory. -#[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct IoVec(pub(crate) libc::iovec, PhantomData); - -impl IoVec { - /// View the `IoVec` as a Rust slice. - #[inline] - pub fn as_slice(&self) -> &[u8] { - use std::slice; - - unsafe { - slice::from_raw_parts( - self.0.iov_base as *const u8, - self.0.iov_len as usize) - } - } -} - -impl<'a> IoVec<&'a [u8]> { - #[cfg(all(feature = "mount", target_os = "freebsd"))] - pub(crate) fn from_raw_parts(base: *mut c_void, len: usize) -> Self { - IoVec(libc::iovec { - iov_base: base, - iov_len: len - }, PhantomData) - } - - /// Create an `IoVec` from a Rust slice. - pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> { - IoVec(libc::iovec { - iov_base: buf.as_ptr() as *mut c_void, - iov_len: buf.len() as size_t, - }, PhantomData) - } -} - -impl<'a> IoVec<&'a mut [u8]> { - /// Create an `IoVec` from a mutable Rust slice. - pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> { - IoVec(libc::iovec { - iov_base: buf.as_ptr() as *mut c_void, - iov_len: buf.len() as size_t, - }, PhantomData) - } -} - -// The only reason IoVec isn't automatically Send+Sync is because libc::iovec -// contains raw pointers. -unsafe impl Send for IoVec where T: Send {} -unsafe impl Sync for IoVec where T: Sync {} diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index c18442fd04..2aac795851 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -72,7 +72,7 @@ pub fn test_timestamping() { recvmsg, sendmsg, setsockopt, socket, sockopt::Timestamping, ControlMessageOwned, MsgFlags, SockaddrIn, SockFlag, SockType, TimestampingFlag, }; - use nix::sys::uio::IoVec; + use std::io::{IoSlice, IoSliceMut}; let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap(); @@ -98,11 +98,12 @@ pub fn test_timestamping() { let sbuf = [0u8; 2048]; let mut rbuf = [0u8; 2048]; let flags = MsgFlags::empty(); - let iov1 = [IoVec::from_slice(&sbuf)]; - let iov2 = [IoVec::from_mut_slice(&mut rbuf)]; + let iov1 = [IoSlice::new(&sbuf)]; + let mut iov2 = [IoSliceMut::new(&mut rbuf)]; + let mut cmsg = cmsg_space!(nix::sys::socket::Timestamps); sendmsg(ssock, &iov1, &[], flags, Some(&sock_addr)).unwrap(); - let recv = recvmsg::<()>(rsock, &iov2, Some(&mut cmsg), flags).unwrap(); + let recv = recvmsg::<()>(rsock, &mut iov2, Some(&mut cmsg), flags).unwrap(); let mut ts = None; for c in recv.cmsgs() { @@ -327,8 +328,8 @@ mod recvfrom { #[cfg(target_os = "linux")] mod udp_offload { use super::*; - use nix::sys::uio::IoVec; use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment}; + use std::io::IoSlice; #[test] // Disable the test under emulation because it fails in Cirrus-CI. Lack @@ -363,7 +364,7 @@ mod recvfrom { let mut num_packets_received: i32 = 0; sendrecv(rsock, ssock, move |s, m, flags| { - let iov = [IoVec::from_slice(m)]; + let iov = [IoSlice::new(m)]; let cmsg = ControlMessage::UdpGsoSegments(&segment_size); sendmsg(s, &iov, &[cmsg], flags, Some(&sock_addr)) }, { @@ -411,7 +412,7 @@ mod recvfrom { ))] #[test] pub fn udp_sendmmsg() { - use nix::sys::uio::IoVec; + use std::io::IoSlice; let std_sa = SocketAddrV4::from_str("127.0.0.1:6793").unwrap(); let std_sa2 = SocketAddrV4::from_str("127.0.0.1:6794").unwrap(); @@ -432,7 +433,7 @@ mod recvfrom { ).expect("send socket failed"); let from = sendrecv(rsock, ssock, move |s, m, flags| { - let iov = [IoVec::from_slice(m)]; + let iov = [IoSlice::new(m)]; let mut msgs = vec![ SendMmsgData { iov: &iov, @@ -475,7 +476,7 @@ mod recvfrom { ))] #[test] pub fn udp_recvmmsg() { - use nix::sys::uio::IoVec; + use std::io::IoSliceMut; use nix::sys::socket::{MsgFlags, recvmmsg}; const NUM_MESSAGES_SENT: usize = 2; @@ -508,7 +509,7 @@ mod recvfrom { // Buffers to receive exactly `NUM_MESSAGES_SENT` messages let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT]; let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| { - [IoVec::from_mut_slice(&mut buf[..])] + [IoSliceMut::new(&mut buf[..])] }).collect(); for iov in &iovs { @@ -541,8 +542,8 @@ mod recvfrom { ))] #[test] pub fn udp_recvmmsg_dontwait_short_read() { - use nix::sys::uio::IoVec; use nix::sys::socket::{MsgFlags, recvmmsg}; + use std::io::IoSliceMut; const NUM_MESSAGES_SENT: usize = 2; const DATA: [u8; 4] = [1,2,3,4]; @@ -579,7 +580,7 @@ mod recvfrom { // kernel buffers when using `MSG_DONTWAIT`. let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT + 2]; let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| { - [IoVec::from_mut_slice(&mut buf[..])] + [IoSliceMut::new(&mut buf[..])] }).collect(); for iov in &iovs { @@ -608,12 +609,14 @@ mod recvfrom { pub fn test_recvmsg_ebadf() { use nix::errno::Errno; use nix::sys::socket::{MsgFlags, recvmsg}; - use nix::sys::uio::IoVec; + use std::io::IoSliceMut; let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; + let mut iov = [IoSliceMut::new(&mut buf[..])]; + let fd = -1; // Bad file descriptor - let r = recvmsg::<()>(fd, &iov, None, MsgFlags::empty()); + let r = recvmsg::<()>(fd, &mut iov, None, MsgFlags::empty()); + assert_eq!(r.err().unwrap(), Errno::EBADF); } @@ -622,11 +625,11 @@ pub fn test_recvmsg_ebadf() { #[cfg_attr(qemu, ignore)] #[test] pub fn test_scm_rights() { - use nix::sys::uio::IoVec; use nix::unistd::{pipe, read, write, close}; use nix::sys::socket::{socketpair, sendmsg, recvmsg, AddressFamily, SockType, SockFlag, ControlMessage, ControlMessageOwned, MsgFlags}; + use std::io::{IoSlice, IoSliceMut}; let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) .unwrap(); @@ -634,7 +637,7 @@ pub fn test_scm_rights() { let mut received_r: Option = None; { - let iov = [IoVec::from_slice(b"hello")]; + let iov = [IoSlice::new(b"hello")]; let fds = [r]; let cmsg = ControlMessage::ScmRights(&fds); assert_eq!(sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5); @@ -644,9 +647,10 @@ pub fn test_scm_rights() { { let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; + + let mut iov = [IoSliceMut::new(&mut buf[..])]; let mut cmsgspace = cmsg_space!([RawFd; 1]); - let msg = recvmsg::<()>(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); + let msg = recvmsg::<()>(fd2, &mut iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); for cmsg in msg.cmsgs() { if let ControlMessageOwned::ScmRights(fd) = cmsg { @@ -677,12 +681,12 @@ pub fn test_scm_rights() { #[cfg_attr(qemu, ignore)] #[test] pub fn test_af_alg_cipher() { - use nix::sys::uio::IoVec; use nix::unistd::read; use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt, AddressFamily, SockType, SockFlag, AlgAddr, ControlMessage, MsgFlags}; use nix::sys::socket::sockopt::AlgSetKey; + use std::io::IoSlice; skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1352"); // Travis's seccomp profile blocks AF_ALG @@ -713,7 +717,7 @@ pub fn test_af_alg_cipher() { let session_socket = accept(sock).expect("accept failed"); let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_ENCRYPT), ControlMessage::AlgSetIv(iv.as_slice())]; - let iov = IoVec::from_slice(&payload); + let iov = IoSlice::new(&payload); sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt"); // allocate buffer for encrypted data @@ -721,7 +725,7 @@ pub fn test_af_alg_cipher() { let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt"); assert_eq!(num_bytes, payload_len); - let iov = IoVec::from_slice(&encrypted); + let iov = IoSlice::new(&encrypted); let iv = vec![1u8; iv_len]; @@ -744,12 +748,12 @@ pub fn test_af_alg_cipher() { pub fn test_af_alg_aead() { use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT}; use nix::fcntl::{fcntl, FcntlArg, OFlag}; - use nix::sys::uio::IoVec; use nix::unistd::{read, close}; use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt, AddressFamily, SockType, SockFlag, AlgAddr, ControlMessage, MsgFlags}; use nix::sys::socket::sockopt::{AlgSetKey, AlgSetAeadAuthSize}; + use std::io::IoSlice; skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1352"); // Travis's seccomp profile blocks AF_ALG @@ -794,7 +798,8 @@ pub fn test_af_alg_aead() { ControlMessage::AlgSetOp(&ALG_OP_ENCRYPT), ControlMessage::AlgSetIv(iv.as_slice()), ControlMessage::AlgSetAeadAssoclen(&assoc_size)]; - let iov = IoVec::from_slice(&payload); + + let iov = IoSlice::new(&payload); sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt"); // allocate buffer for encrypted data @@ -807,7 +812,7 @@ pub fn test_af_alg_aead() { encrypted[i as usize] = 10; } - let iov = IoVec::from_slice(&encrypted); + let iov = IoSlice::new(&encrypted); let iv = vec![1u8; iv_len]; @@ -846,10 +851,10 @@ pub fn test_af_alg_aead() { #[test] pub fn test_sendmsg_ipv4packetinfo() { use cfg_if::cfg_if; - use nix::sys::uio::IoVec; use nix::sys::socket::{socket, sendmsg, bind, AddressFamily, SockType, SockFlag, SockaddrIn, ControlMessage, MsgFlags}; + use std::io::IoSlice; let sock = socket(AddressFamily::Inet, SockType::Datagram, @@ -862,7 +867,7 @@ pub fn test_sendmsg_ipv4packetinfo() { bind(sock, &sock_addr).expect("bind failed"); let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; + let iov = [IoSlice::new(&slice)]; cfg_if! { if #[cfg(target_os = "netbsd")] { @@ -900,10 +905,10 @@ pub fn test_sendmsg_ipv4packetinfo() { #[test] pub fn test_sendmsg_ipv6packetinfo() { use nix::errno::Errno; - use nix::sys::uio::IoVec; use nix::sys::socket::{socket, sendmsg, bind, AddressFamily, SockType, SockFlag, SockaddrIn6, ControlMessage, MsgFlags}; + use std::io::IoSlice; let sock = socket(AddressFamily::Inet6, SockType::Datagram, @@ -920,7 +925,7 @@ pub fn test_sendmsg_ipv6packetinfo() { } let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; + let iov = [IoSlice::new(&slice)]; let pi = libc::in6_pktinfo { ipi6_ifindex: 0, /* Unspecified interface */ @@ -944,16 +949,17 @@ fn test_scm_rights_single_cmsg_multiple_fds() { use std::thread; use nix::sys::socket::{ControlMessage, ControlMessageOwned, MsgFlags, sendmsg, recvmsg}; - use nix::sys::uio::IoVec; + use std::io::{IoSlice, IoSliceMut}; let (send, receive) = UnixDatagram::pair().unwrap(); let thread = thread::spawn(move || { let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; + let mut iovec = [IoSliceMut::new(&mut buf)]; + let mut space = cmsg_space!([RawFd; 2]); let msg = recvmsg::<()>( receive.as_raw_fd(), - &iovec, + &mut iovec, Some(&mut space), MsgFlags::empty() ).unwrap(); @@ -971,11 +977,11 @@ fn test_scm_rights_single_cmsg_multiple_fds() { assert!(cmsgs.next().is_none(), "unexpected control msg"); assert_eq!(msg.bytes, 8); - assert_eq!(iovec[0].as_slice(), [1u8, 2, 3, 4, 5, 6, 7, 8]); + assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]); }); let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; + let iov = [IoSlice::new(&slice)]; let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO]; // pass stdin and stdout let cmsg = [ControlMessage::ScmRights(&fds)]; sendmsg::<()>(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap(); @@ -988,25 +994,26 @@ fn test_scm_rights_single_cmsg_multiple_fds() { // raw `sendmsg`. #[test] pub fn test_sendmsg_empty_cmsgs() { - use nix::sys::uio::IoVec; use nix::unistd::close; use nix::sys::socket::{socketpair, sendmsg, recvmsg, AddressFamily, SockType, SockFlag, MsgFlags}; + use std::io::{IoSlice, IoSliceMut}; let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) .unwrap(); { - let iov = [IoVec::from_slice(b"hello")]; + let iov = [IoSlice::new(b"hello")]; assert_eq!(sendmsg::<()>(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5); close(fd1).unwrap(); } { let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; + let mut iov = [IoSliceMut::new(&mut buf[..])]; + let mut cmsgspace = cmsg_space!([RawFd; 1]); - let msg = recvmsg::<()>(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); + let msg = recvmsg::<()>(fd2, &mut iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); for _ in msg.cmsgs() { panic!("unexpected cmsg"); @@ -1025,7 +1032,6 @@ pub fn test_sendmsg_empty_cmsgs() { ))] #[test] fn test_scm_credentials() { - use nix::sys::uio::IoVec; use nix::unistd::{close, getpid, getuid, getgid}; use nix::sys::socket::{socketpair, sendmsg, recvmsg, AddressFamily, SockType, SockFlag, @@ -1033,6 +1039,7 @@ fn test_scm_credentials() { UnixCredentials}; #[cfg(any(target_os = "android", target_os = "linux"))] use nix::sys::socket::{setsockopt, sockopt::PassCred}; + use std::io::{IoSlice, IoSliceMut}; let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) .unwrap(); @@ -1040,7 +1047,7 @@ fn test_scm_credentials() { setsockopt(recv, PassCred, &true).unwrap(); { - let iov = [IoVec::from_slice(b"hello")]; + let iov = [IoSlice::new(b"hello")]; #[cfg(any(target_os = "android", target_os = "linux"))] let cred = UnixCredentials::new(); #[cfg(any(target_os = "android", target_os = "linux"))] @@ -1053,9 +1060,10 @@ fn test_scm_credentials() { { let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; + let mut iov = [IoSliceMut::new(&mut buf[..])]; + let mut cmsgspace = cmsg_space!(UnixCredentials); - let msg = recvmsg::<()>(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); + let msg = recvmsg::<()>(recv, &mut iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); let mut received_cred = None; for cmsg in msg.cmsgs() { @@ -1106,12 +1114,12 @@ fn test_too_large_cmsgspace() { #[cfg(any(target_os = "android", target_os = "linux"))] fn test_impl_scm_credentials_and_rights(mut space: Vec) { use libc::ucred; - use nix::sys::uio::IoVec; use nix::unistd::{pipe, write, close, getpid, getuid, getgid}; use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt, SockType, SockFlag, ControlMessage, ControlMessageOwned, MsgFlags}; use nix::sys::socket::sockopt::PassCred; + use std::io::{IoSlice, IoSliceMut}; let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) .unwrap(); @@ -1121,7 +1129,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec) { let mut received_r: Option = None; { - let iov = [IoVec::from_slice(b"hello")]; + let iov = [IoSlice::new(b"hello")]; let cred = ucred { pid: getpid().as_raw(), uid: getuid().as_raw(), @@ -1139,8 +1147,8 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec) { { let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; - let msg = recvmsg::<()>(recv, &iov, Some(&mut space), MsgFlags::empty()).unwrap(); + let mut iov = [IoSliceMut::new(&mut buf[..])]; + let msg = recvmsg::<()>(recv, &mut iov, Some(&mut space), MsgFlags::empty()).unwrap(); let mut received_cred = None; assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs"); @@ -1289,8 +1297,8 @@ pub fn test_recv_ipv4pktinfo() { use nix::sys::socket::{bind, SockaddrIn, SockFlag, SockType}; use nix::sys::socket::{getsockname, setsockopt, socket}; use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use nix::sys::uio::IoVec; use nix::net::if_::*; + use std::io::{IoSlice, IoSliceMut}; let lo_ifaddr = loopback_address(AddressFamily::Inet); let (lo_name, lo) = match lo_ifaddr { @@ -1310,7 +1318,7 @@ pub fn test_recv_ipv4pktinfo() { { let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; + let iov = [IoSlice::new(&slice)]; let send = socket( AddressFamily::Inet, @@ -1323,11 +1331,12 @@ pub fn test_recv_ipv4pktinfo() { { let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; + let mut iovec = [IoSliceMut::new(&mut buf)]; + let mut space = cmsg_space!(libc::in_pktinfo); let msg = recvmsg::<()>( receive, - &iovec, + &mut iovec, Some(&mut space), MsgFlags::empty(), ).expect("recvmsg failed"); @@ -1350,7 +1359,7 @@ pub fn test_recv_ipv4pktinfo() { assert!(cmsgs.next().is_none(), "unexpected additional control msg"); assert_eq!(msg.bytes, 8); assert_eq!( - iovec[0].as_slice(), + *iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8] ); } @@ -1379,7 +1388,7 @@ pub fn test_recvif() { use nix::sys::socket::{bind, SockaddrIn, SockFlag, SockType}; use nix::sys::socket::{getsockname, setsockopt, socket}; use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use nix::sys::uio::IoVec; + use std::io::{IoSlice, IoSliceMut}; let lo_ifaddr = loopback_address(AddressFamily::Inet); let (lo_name, lo) = match lo_ifaddr { @@ -1400,7 +1409,7 @@ pub fn test_recvif() { { let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; + let iov = [IoSlice::new(&slice)]; let send = socket( AddressFamily::Inet, @@ -1413,11 +1422,11 @@ pub fn test_recvif() { { let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; + let mut iovec = [IoSliceMut::new(&mut buf)]; let mut space = cmsg_space!(libc::sockaddr_dl, libc::in_addr); let msg = recvmsg::<()>( receive, - &iovec, + &mut iovec, Some(&mut space), MsgFlags::empty(), ).expect("recvmsg failed"); @@ -1461,7 +1470,7 @@ pub fn test_recvif() { assert!(rx_recvdstaddr); assert_eq!(msg.bytes, 8); assert_eq!( - iovec[0].as_slice(), + *iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8] ); } @@ -1492,7 +1501,7 @@ pub fn test_recv_ipv6pktinfo() { use nix::sys::socket::{bind, SockaddrIn6, SockFlag, SockType}; use nix::sys::socket::{getsockname, setsockopt, socket}; use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use nix::sys::uio::IoVec; + use std::io::{IoSlice, IoSliceMut}; let lo_ifaddr = loopback_address(AddressFamily::Inet6); let (lo_name, lo) = match lo_ifaddr { @@ -1512,7 +1521,7 @@ pub fn test_recv_ipv6pktinfo() { { let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; + let iov = [IoSlice::new(&slice)]; let send = socket( AddressFamily::Inet6, @@ -1525,11 +1534,12 @@ pub fn test_recv_ipv6pktinfo() { { let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; + let mut iovec = [IoSliceMut::new(&mut buf)]; + let mut space = cmsg_space!(libc::in6_pktinfo); let msg = recvmsg::<()>( receive, - &iovec, + &mut iovec, Some(&mut space), MsgFlags::empty(), ).expect("recvmsg failed"); @@ -1553,7 +1563,7 @@ pub fn test_recv_ipv6pktinfo() { assert!(cmsgs.next().is_none(), "unexpected additional control msg"); assert_eq!(msg.bytes, 8); assert_eq!( - iovec[0].as_slice(), + *iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8] ); } @@ -1611,7 +1621,7 @@ pub fn test_vsock() { #[test] fn test_recvmsg_timestampns() { use nix::sys::socket::*; - use nix::sys::uio::IoVec; + use std::io::{IoSlice, IoSliceMut}; use nix::sys::time::*; use std::time::*; @@ -1629,15 +1639,16 @@ fn test_recvmsg_timestampns() { // Get initial time let time0 = SystemTime::now(); // Send the message - let iov = [IoVec::from_slice(message)]; + let iov = [IoSlice::new(message)]; let flags = MsgFlags::empty(); let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap(); assert_eq!(message.len(), l); // Receive the message let mut buffer = vec![0u8; message.len()]; let mut cmsgspace = nix::cmsg_space!(TimeSpec); - let iov = [IoVec::from_mut_slice(&mut buffer)]; - let r = recvmsg::<()>(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap(); + + let mut iov = [IoSliceMut::new(&mut buffer)]; + let r = recvmsg::<()>(in_socket, &mut iov, Some(&mut cmsgspace), flags).unwrap(); let rtime = match r.cmsgs().next() { Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime, Some(_) => panic!("Unexpected control message"), @@ -1662,7 +1673,7 @@ fn test_recvmsg_timestampns() { #[test] fn test_recvmmsg_timestampns() { use nix::sys::socket::*; - use nix::sys::uio::IoVec; + use std::io::{IoSlice, IoSliceMut}; use nix::sys::time::*; use std::time::*; @@ -1680,14 +1691,14 @@ fn test_recvmmsg_timestampns() { // Get initial time let time0 = SystemTime::now(); // Send the message - let iov = [IoVec::from_slice(message)]; + let iov = [IoSlice::new(message)]; let flags = MsgFlags::empty(); let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap(); assert_eq!(message.len(), l); // Receive the message let mut buffer = vec![0u8; message.len()]; let mut cmsgspace = nix::cmsg_space!(TimeSpec); - let iov = [IoVec::from_mut_slice(&mut buffer)]; + let iov = [IoSliceMut::new(&mut buffer)]; let mut data = vec![ RecvMmsgData { iov, @@ -1720,7 +1731,7 @@ fn test_recvmmsg_timestampns() { fn test_recvmsg_rxq_ovfl() { use nix::Error; use nix::sys::socket::*; - use nix::sys::uio::IoVec; + use std::io::{IoSlice, IoSliceMut}; use nix::sys::socket::sockopt::{RxqOvfl, RcvBuf}; let message = [0u8; 2048]; @@ -1752,7 +1763,7 @@ fn test_recvmsg_rxq_ovfl() { let mut drop_counter = 0; for _ in 0..2 { - let iov = [IoVec::from_slice(&message)]; + let iov = [IoSlice::new(&message)]; let flags = MsgFlags::empty(); // Send the 3 messages (the receiver buffer can only hold 2 messages) @@ -1767,11 +1778,11 @@ fn test_recvmsg_rxq_ovfl() { let mut buffer = vec![0u8; message.len()]; let mut cmsgspace = nix::cmsg_space!(u32); - let iov = [IoVec::from_mut_slice(&mut buffer)]; + let mut iov = [IoSliceMut::new(&mut buffer)]; match recvmsg::<()>( in_socket, - &iov, + &mut iov, Some(&mut cmsgspace), MsgFlags::MSG_DONTWAIT) { Ok(r) => { @@ -1904,7 +1915,7 @@ mod linux_errqueue { TESTF: FnOnce(&ControlMessageOwned) -> libc::sock_extended_err, { use nix::errno::Errno; - use nix::sys::uio::IoVec; + use std::io::IoSliceMut; const MESSAGE_CONTENTS: &str = "ABCDEF"; let std_sa = std::net::SocketAddr::from_str(sa).unwrap(); @@ -1918,13 +1929,12 @@ mod linux_errqueue { } let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; + let mut iovec = [IoSliceMut::new(&mut buf)]; let mut cspace = cmsg_space!(libc::sock_extended_err, SA); - let msg = recvmsg(sock, &iovec, Some(&mut cspace), MsgFlags::MSG_ERRQUEUE).unwrap(); + let msg = recvmsg(sock, &mut iovec, Some(&mut cspace), MsgFlags::MSG_ERRQUEUE).unwrap(); // The sent message / destination associated with the error is returned: assert_eq!(msg.bytes, MESSAGE_CONTENTS.as_bytes().len()); - assert_eq!(&buf[..msg.bytes], MESSAGE_CONTENTS.as_bytes()); // recvmsg(2): "The original destination address of the datagram that caused the error is // supplied via msg_name;" however, this is not literally true. E.g., an earlier version // of this test used 0.0.0.0 (::0) as the destination address, which was mutated into @@ -1945,6 +1955,9 @@ mod linux_errqueue { assert_eq!(ext_err.ee_code, ee_code); // ip(7): ee_info contains the discovered MTU for EMSGSIZE errors. assert_eq!(ext_err.ee_info, 0); + + let bytes = msg.bytes; + assert_eq!(&buf[..bytes], MESSAGE_CONTENTS.as_bytes()); } } @@ -1989,7 +2002,7 @@ pub fn test_txtime() { bind(rsock, &sock_addr).unwrap(); let sbuf = [0u8; 2048]; - let iov1 = [nix::sys::uio::IoVec::from_slice(&sbuf)]; + let iov1 = [std::io::IoSlice::new(&sbuf)]; let now = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap(); let delay = std::time::Duration::from_secs(1).into(); @@ -1999,6 +2012,6 @@ pub fn test_txtime() { sendmsg(ssock, &iov1, &[cmsg], MsgFlags::empty(), Some(&sock_addr)).unwrap(); let mut rbuf = [0u8; 2048]; - let iov2 = [nix::sys::uio::IoVec::from_mut_slice(&mut rbuf)]; - recvmsg::<()>(rsock, &iov2, None, MsgFlags::empty()).unwrap(); + let mut iov2 = [std::io::IoSliceMut::new(&mut rbuf)]; + recvmsg::<()>(rsock, &mut iov2, None, MsgFlags::empty()).unwrap(); } diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs index 5353c516e4..7dd12a21b0 100644 --- a/test/sys/test_uio.rs +++ b/test/sys/test_uio.rs @@ -4,8 +4,12 @@ use rand::{thread_rng, Rng}; use rand::distributions::Alphanumeric; use std::{cmp, iter}; use std::fs::{OpenOptions}; +use std::io::IoSlice; use std::os::unix::io::AsRawFd; +#[cfg(not(target_os = "redox"))] +use std::io::IoSliceMut; + #[cfg(not(target_os = "redox"))] use tempfile::tempfile; use tempfile::tempdir; @@ -29,7 +33,7 @@ fn test_writev() { let left = to_write.len() - consumed; let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64..cmp::min(256, left)) }; let b = &to_write[consumed..consumed+slice_len]; - iovecs.push(IoVec::from_slice(b)); + iovecs.push(IoSlice::new(b)); consumed += slice_len; } let pipe_res = pipe(); @@ -78,7 +82,7 @@ fn test_readv() { } let mut iovecs = Vec::with_capacity(storage.len()); for v in &mut storage { - iovecs.push(IoVec::from_mut_slice(&mut v[..])); + iovecs.push(IoSliceMut::new(&mut v[..])); } let pipe_res = pipe(); assert!(pipe_res.is_ok()); @@ -95,7 +99,7 @@ fn test_readv() { // Cccumulate data from iovecs let mut read_buf = Vec::with_capacity(to_write.len()); for iovec in &iovecs { - read_buf.extend(iovec.as_slice().iter().cloned()); + read_buf.extend(iovec.iter().cloned()); } // Check whether iovecs contain all written data assert_eq!(read_buf.len(), to_write.len()); @@ -149,9 +153,9 @@ fn test_pwritev() { let expected: Vec = [vec![0;100], to_write.clone()].concat(); let iovecs = [ - IoVec::from_slice(&to_write[0..17]), - IoVec::from_slice(&to_write[17..64]), - IoVec::from_slice(&to_write[64..128]), + IoSlice::new(&to_write[0..17]), + IoSlice::new(&to_write[17..64]), + IoSlice::new(&to_write[64..128]), ]; let tempdir = tempdir().unwrap(); @@ -194,9 +198,9 @@ fn test_preadv() { { // Borrow the buffers into IoVecs and preadv into them - let iovecs: Vec<_> = buffers.iter_mut().map( - |buf| IoVec::from_mut_slice(&mut buf[..])).collect(); - assert_eq!(Ok(100), preadv(file.as_raw_fd(), &iovecs, 100)); + let mut iovecs: Vec<_> = buffers.iter_mut().map( + |buf| IoSliceMut::new(&mut buf[..])).collect(); + assert_eq!(Ok(100), preadv(file.as_raw_fd(), &mut iovecs, 100)); } let all = buffers.concat(); @@ -233,7 +237,7 @@ fn test_process_vm_readv() { let mut buf = vec![0u8; 5]; let ret = process_vm_readv(child, - &[IoVec::from_mut_slice(&mut buf)], + &mut [IoSliceMut::new(&mut buf)], &[remote_iov]); kill(child, SIGTERM).unwrap(); diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index 95e224e2d4..ebfc43e25f 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -218,12 +218,11 @@ fn test_readlink() { #[cfg(any(target_os = "linux", target_os = "android"))] mod linux_android { use std::io::prelude::*; - use std::io::SeekFrom; + use std::io::{IoSlice, SeekFrom}; use std::os::unix::prelude::*; use libc::loff_t; use nix::fcntl::*; - use nix::sys::uio::IoVec; use nix::unistd::{close, pipe, read, write}; use tempfile::tempfile; @@ -323,8 +322,8 @@ mod linux_android { let buf1 = b"abcdef"; let buf2 = b"defghi"; let iovecs = vec![ - IoVec::from_slice(&buf1[0..3]), - IoVec::from_slice(&buf2[0..3]) + IoSlice::new(&buf1[0..3]), + IoSlice::new(&buf2[0..3]) ]; let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();