summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authornot_a_seagull <notaseagull048@gmail.com>2022-01-23 11:43:25 -0800
committernot_a_seagull <notaseagull048@gmail.com>2022-04-08 12:39:16 -0700
commit0b58f2977252739629b5175043d705f7fc76ea8d (patch)
treeae028d4613a1c6752fe729e870d4b9ff3c7388b1 /src
parentc59a8c8cc6cc6922888d6f33635905f9ea3d3205 (diff)
downloadnix-0b58f2977252739629b5175043d705f7fc76ea8d.zip
Replace the IoVec type with IoSlice and IoSliceMut
Diffstat (limited to 'src')
-rw-r--r--src/fcntl.rs2
-rw-r--r--src/mount/bsd.rs111
-rw-r--r--src/sys/sendfile.rs16
-rw-r--r--src/sys/socket/mod.rs44
-rw-r--r--src/sys/uio.rs163
5 files changed, 181 insertions, 155 deletions
diff --git a/src/fcntl.rs b/src/fcntl.rs
index 6c713608..fa64c8ea 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<usize>
{
diff --git a/src/mount/bsd.rs b/src/mount/bsd.rs
index ba0c1a28..b4d611ee 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<IoVec<&'a [u8]>>,
+ // n.b. notgull: In reality, this is a list that contains
+ // both mutable and immutable pointers.
+ // Be careful using this.
+ iov: Vec<libc::iovec>,
is_owned: Vec<bool>,
+ 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<P: ?Sized + NixPath>(&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<P: ?Sized + NixPath>(&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 5ec0b526..2ebcdf48 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<Vec<IoVec<&'a [u8]>>>,
- Option<Vec<IoVec<&'a [u8]>>>,
+ Option<Vec<IoSlice<'a>>>,
+ Option<Vec<IoSlice<'a>>>,
);
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<Vec<IoVec<&[u8]>>> =
- headers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect());
- let trailer_iovecs: Option<Vec<IoVec<&[u8]>>> =
- trailers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect());
+ let header_iovecs: Option<Vec<IoSlice<'_>>> =
+ headers.map(|s| s.iter().map(|b| IoSlice::new(b)).collect());
+ let trailer_iovecs: Option<Vec<IoSlice<'_>>> =
+ 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 8dac6eda..c6613892 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::<SockaddrIn>(in_socket, &iov, Some(&mut cmsgspace), flags)
+ /// let mut iov = [IoSliceMut::new(&mut buffer)];
+ /// let r = recvmsg::<SockaddrIn>(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<S>(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
+pub fn sendmsg<S>(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage],
flags: MsgFlags, addr: Option<&S>) -> Result<usize>
where S: SockaddrLike
{
@@ -1420,7 +1418,7 @@ pub fn sendmsg<S>(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<Vec<usize>>
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<u8>>,
@@ -1557,7 +1555,7 @@ pub fn recvmmsg<'a, I, S>(
timeout: Option<crate::sys::time::TimeSpec>
) -> Result<Vec<RecvMsg<'a, S>>>
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<u8>>,
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<u8>>,
flags: MsgFlags) -> Result<RecvMsg<'a, S>>
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 42298300..ba6c64ef 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<usize> {
+pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> {
+ // 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<usize> {
/// 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<usize> {
+pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
+ // 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<usize> {
/// 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<usize> {
+
#[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<usize> {
#[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<usize>{
/// 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<T>(pub(crate) libc::iovec, PhantomData<T>);
+
+#[allow(deprecated)]
+impl<T> IoVec<T> {
+ /// 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<T> Send for IoVec<T> where T: Send {}
+#[allow(deprecated)]
+unsafe impl<T> Sync for IoVec<T> 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<usize>
{
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<usize>
{
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<T>(pub(crate) libc::iovec, PhantomData<T>);
-
-impl<T> IoVec<T> {
- /// 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<T> Send for IoVec<T> where T: Send {}
-unsafe impl<T> Sync for IoVec<T> where T: Sync {}