Upgrade rust/crates/nix to 0.21.0
Test: make
Change-Id: Ic8422bfdc4afc11c6c310e67999ec360d92d843d
diff --git a/src/sys/aio.rs b/src/sys/aio.rs
index 1afdb35..a03caa4 100644
--- a/src/sys/aio.rs
+++ b/src/sys/aio.rs
@@ -25,11 +25,11 @@
use crate::errno::Errno;
use std::os::unix::io::RawFd;
use libc::{c_void, off_t, size_t};
-use std::borrow::{Borrow, BorrowMut};
use std::fmt;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::mem;
+use std::pin::Pin;
use std::ptr::{null, null_mut};
use crate::sys::signal::*;
use std::thread;
@@ -90,120 +90,31 @@
AioAllDone = libc::AIO_ALLDONE,
}
-/// Owns (uniquely or shared) a memory buffer to keep it from `Drop`ing while
-/// the kernel has a pointer to it.
-pub enum Buffer<'a> {
- /// No buffer to own.
- ///
- /// Used for operations like `aio_fsync` that have no data, or for unsafe
- /// operations that work with raw pointers.
- None,
- /// Keeps a reference to a slice
- Phantom(PhantomData<&'a mut [u8]>),
- /// Generic thing that keeps a buffer from dropping
- BoxedSlice(Box<dyn Borrow<[u8]>>),
- /// Generic thing that keeps a mutable buffer from dropping
- BoxedMutSlice(Box<dyn BorrowMut<[u8]>>),
-}
+/// Newtype that adds Send and Sync to libc::aiocb, which contains raw pointers
+#[repr(transparent)]
+struct LibcAiocb(libc::aiocb);
-impl<'a> Debug for Buffer<'a> {
- // Note: someday it may be possible to Derive Debug for a trait object, but
- // not today.
- // https://github.com/rust-lang/rust/issues/1563
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Buffer::None => write!(fmt, "None"),
- Buffer::Phantom(p) => p.fmt(fmt),
- Buffer::BoxedSlice(ref bs) => {
- let borrowed : &dyn Borrow<[u8]> = bs.borrow();
- write!(fmt, "BoxedSlice({:?})",
- borrowed as *const dyn Borrow<[u8]>)
- },
- Buffer::BoxedMutSlice(ref bms) => {
- let borrowed : &dyn BorrowMut<[u8]> = bms.borrow();
- write!(fmt, "BoxedMutSlice({:?})",
- borrowed as *const dyn BorrowMut<[u8]>)
- }
- }
- }
-}
+unsafe impl Send for LibcAiocb {}
+unsafe impl Sync for LibcAiocb {}
/// AIO Control Block.
///
/// The basic structure used by all aio functions. Each `AioCb` represents one
/// I/O request.
pub struct AioCb<'a> {
- aiocb: libc::aiocb,
+ aiocb: LibcAiocb,
/// Tracks whether the buffer pointed to by `libc::aiocb.aio_buf` is mutable
mutable: bool,
/// Could this `AioCb` potentially have any in-kernel state?
in_progress: bool,
- /// Optionally keeps a reference to the data.
- ///
- /// Used to keep buffers from `Drop`'ing, and may be returned once the
- /// `AioCb` is completed by [`buffer`](#method.buffer).
- buffer: Buffer<'a>
+ _buffer: std::marker::PhantomData<&'a [u8]>,
+ _pin: std::marker::PhantomPinned
}
impl<'a> AioCb<'a> {
- /// Remove the inner `Buffer` and return it
- ///
- /// It is an error to call this method while the `AioCb` is still in
- /// progress.
- pub fn buffer(&mut self) -> Buffer<'a> {
- assert!(!self.in_progress);
- let mut x = Buffer::None;
- mem::swap(&mut self.buffer, &mut x);
- x
- }
-
- /// Remove the inner boxed slice, if any, and return it.
- ///
- /// The returned value will be the argument that was passed to
- /// `from_boxed_slice` when this `AioCb` was created.
- ///
- /// It is an error to call this method while the `AioCb` is still in
- /// progress.
- pub fn boxed_slice(&mut self) -> Option<Box<dyn Borrow<[u8]>>> {
- assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress. Did you forget to call aio_return?");
- if let Buffer::BoxedSlice(_) = self.buffer {
- let mut oldbuffer = Buffer::None;
- mem::swap(&mut self.buffer, &mut oldbuffer);
- if let Buffer::BoxedSlice(inner) = oldbuffer {
- Some(inner)
- } else {
- unreachable!();
- }
- } else {
- None
- }
- }
-
- /// Remove the inner boxed mutable slice, if any, and return it.
- ///
- /// The returned value will be the argument that was passed to
- /// `from_boxed_mut_slice` when this `AioCb` was created.
- ///
- /// It is an error to call this method while the `AioCb` is still in
- /// progress.
- pub fn boxed_mut_slice(&mut self) -> Option<Box<dyn BorrowMut<[u8]>>> {
- assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress. Did you forget to call aio_return?");
- if let Buffer::BoxedMutSlice(_) = self.buffer {
- let mut oldbuffer = Buffer::None;
- mem::swap(&mut self.buffer, &mut oldbuffer);
- if let Buffer::BoxedMutSlice(inner) = oldbuffer {
- Some(inner)
- } else {
- unreachable!();
- }
- } else {
- None
- }
- }
-
/// Returns the underlying file descriptor associated with the `AioCb`
pub fn fd(&self) -> RawFd {
- self.aiocb.aio_fildes
+ self.aiocb.0.aio_fildes
}
/// Constructs a new `AioCb` with no associated buffer.
@@ -243,17 +154,39 @@
/// # }
/// ```
pub fn from_fd(fd: RawFd, prio: libc::c_int,
- sigev_notify: SigevNotify) -> AioCb<'a> {
+ sigev_notify: SigevNotify) -> Pin<Box<AioCb<'a>>> {
let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = 0;
- a.aio_nbytes = 0;
- a.aio_buf = null_mut();
+ a.0.aio_offset = 0;
+ a.0.aio_nbytes = 0;
+ a.0.aio_buf = null_mut();
- AioCb {
+ Box::pin(AioCb {
aiocb: a,
mutable: false,
in_progress: false,
- buffer: Buffer::None
+ _buffer: PhantomData,
+ _pin: std::marker::PhantomPinned
+ })
+ }
+
+ // Private helper
+ #[cfg(not(any(target_os = "ios", target_os = "macos")))]
+ fn from_mut_slice_unpinned(fd: RawFd, offs: off_t, buf: &'a mut [u8],
+ prio: libc::c_int, sigev_notify: SigevNotify,
+ opcode: LioOpcode) -> AioCb<'a>
+ {
+ let mut a = AioCb::common_init(fd, prio, sigev_notify);
+ a.0.aio_offset = offs;
+ a.0.aio_nbytes = buf.len() as size_t;
+ a.0.aio_buf = buf.as_ptr() as *mut c_void;
+ a.0.aio_lio_opcode = opcode as libc::c_int;
+
+ AioCb {
+ aiocb: a,
+ mutable: true,
+ in_progress: false,
+ _buffer: PhantomData,
+ _pin: std::marker::PhantomPinned
}
}
@@ -262,8 +195,7 @@
/// The resulting `AioCb` will be suitable for both read and write
/// operations, but only if the borrow checker can guarantee that the slice
/// will outlive the `AioCb`. That will usually be the case if the `AioCb`
- /// is stack-allocated. If the borrow checker gives you trouble, try using
- /// [`from_boxed_mut_slice`](#method.from_boxed_mut_slice) instead.
+ /// is stack-allocated.
///
/// # Parameters
///
@@ -316,210 +248,20 @@
/// ```
pub fn from_mut_slice(fd: RawFd, offs: off_t, buf: &'a mut [u8],
prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
+ opcode: LioOpcode) -> Pin<Box<AioCb<'a>>> {
let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = offs;
- a.aio_nbytes = buf.len() as size_t;
- a.aio_buf = buf.as_ptr() as *mut c_void;
- a.aio_lio_opcode = opcode as libc::c_int;
+ a.0.aio_offset = offs;
+ a.0.aio_nbytes = buf.len() as size_t;
+ a.0.aio_buf = buf.as_ptr() as *mut c_void;
+ a.0.aio_lio_opcode = opcode as libc::c_int;
- AioCb {
+ Box::pin(AioCb {
aiocb: a,
mutable: true,
in_progress: false,
- buffer: Buffer::Phantom(PhantomData),
- }
- }
-
- /// The safest and most flexible way to create an `AioCb`.
- ///
- /// Unlike [`from_slice`], this method returns a structure suitable for
- /// placement on the heap. It may be used for write operations, but not
- /// read operations. Unlike `from_ptr`, this method will ensure that the
- /// buffer doesn't `drop` while the kernel is still processing it. Any
- /// object that can be borrowed as a boxed slice will work.
- ///
- /// # Parameters
- ///
- /// * `fd`: File descriptor. Required for all aio functions.
- /// * `offs`: File offset
- /// * `buf`: A boxed slice-like object
- /// * `prio`: If POSIX Prioritized IO is supported, then the
- /// operation will be prioritized at the process's
- /// priority level minus `prio`
- /// * `sigev_notify`: Determines how you will be notified of event
- /// completion.
- /// * `opcode`: This field is only used for `lio_listio`. It
- /// determines which operation to use for this individual
- /// aiocb
- ///
- /// # Examples
- ///
- /// Create an `AioCb` from a Vector and use it for writing
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::{thread, time};
- /// # use std::io::Write;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// let wbuf = Box::new(Vec::from("CDEF"));
- /// let expected_len = wbuf.len();
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
- /// 2, //offset
- /// wbuf,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// aiocb.write().unwrap();
- /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// assert_eq!(aiocb.aio_return().unwrap() as usize, expected_len);
- /// # }
- /// ```
- ///
- /// Create an `AioCb` from a `Bytes` object
- ///
- /// ```
- /// # use bytes::Bytes;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// let wbuf = Box::new(Bytes::from(&b"CDEF"[..]));
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
- /// 2, //offset
- /// wbuf,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// # }
- /// ```
- ///
- /// If a library needs to work with buffers that aren't `Box`ed, it can
- /// create a `Box`ed container for use with this method. Here's an example
- /// using an un`Box`ed `Bytes` object.
- ///
- /// ```
- /// # use bytes::Bytes;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::borrow::Borrow;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// struct BytesContainer(Bytes);
- /// impl Borrow<[u8]> for BytesContainer {
- /// fn borrow(&self) -> &[u8] {
- /// self.0.as_ref()
- /// }
- /// }
- /// fn main() {
- /// let wbuf = Bytes::from(&b"CDEF"[..]);
- /// let boxed_wbuf = Box::new(BytesContainer(wbuf));
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
- /// 2, //offset
- /// boxed_wbuf,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// }
- /// ```
- ///
- /// [`from_slice`]: #method.from_slice
- pub fn from_boxed_slice(fd: RawFd, offs: off_t, buf: Box<dyn Borrow<[u8]>>,
- prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- {
- let borrowed : &dyn Borrow<[u8]> = buf.borrow();
- let slice : &[u8] = borrowed.borrow();
- a.aio_nbytes = slice.len() as size_t;
- a.aio_buf = slice.as_ptr() as *mut c_void;
- }
- a.aio_offset = offs;
- a.aio_lio_opcode = opcode as libc::c_int;
-
- AioCb {
- aiocb: a,
- mutable: false,
- in_progress: false,
- buffer: Buffer::BoxedSlice(buf),
- }
- }
-
- /// The safest and most flexible way to create an `AioCb` for reading.
- ///
- /// Like [`from_boxed_slice`], but the slice is a mutable one. More
- /// flexible than [`from_mut_slice`], because a wide range of objects can be
- /// used.
- ///
- /// # Examples
- ///
- /// Create an `AioCb` from a Vector and use it for reading
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::{thread, time};
- /// # use std::io::Write;
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// # fn main() {
- /// const INITIAL: &[u8] = b"abcdef123456";
- /// const LEN: usize = 4;
- /// let rbuf = Box::new(vec![0; LEN]);
- /// let mut f = tempfile().unwrap();
- /// f.write_all(INITIAL).unwrap();
- /// let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
- /// 2, //offset
- /// rbuf,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_NOP);
- /// aiocb.read().unwrap();
- /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// assert_eq!(aiocb.aio_return().unwrap() as usize, LEN);
- /// let mut buffer = aiocb.boxed_mut_slice().unwrap();
- /// const EXPECT: &[u8] = b"cdef";
- /// assert_eq!(buffer.borrow_mut(), EXPECT);
- /// # }
- /// ```
- ///
- /// [`from_boxed_slice`]: #method.from_boxed_slice
- /// [`from_mut_slice`]: #method.from_mut_slice
- pub fn from_boxed_mut_slice(fd: RawFd, offs: off_t,
- mut buf: Box<dyn BorrowMut<[u8]>>,
- prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- {
- let borrowed : &mut dyn BorrowMut<[u8]> = buf.borrow_mut();
- let slice : &mut [u8] = borrowed.borrow_mut();
- a.aio_nbytes = slice.len() as size_t;
- a.aio_buf = slice.as_mut_ptr() as *mut c_void;
- }
- a.aio_offset = offs;
- a.aio_lio_opcode = opcode as libc::c_int;
-
- AioCb {
- aiocb: a,
- mutable: true,
- in_progress: false,
- buffer: Buffer::BoxedMutSlice(buf),
- }
+ _buffer: PhantomData,
+ _pin: std::marker::PhantomPinned
+ })
}
/// Constructs a new `AioCb` from a mutable raw pointer
@@ -527,8 +269,7 @@
/// Unlike `from_mut_slice`, this method returns a structure suitable for
/// placement on the heap. It may be used for both reads and writes. Due
/// to its unsafety, this method is not recommended. It is most useful when
- /// heap allocation is required but for some reason the data cannot be
- /// wrapped in a `struct` that implements `BorrowMut<[u8]>`
+ /// heap allocation is required.
///
/// # Parameters
///
@@ -552,28 +293,27 @@
pub unsafe fn from_mut_ptr(fd: RawFd, offs: off_t,
buf: *mut c_void, len: usize,
prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
+ opcode: LioOpcode) -> Pin<Box<AioCb<'a>>> {
let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = offs;
- a.aio_nbytes = len;
- a.aio_buf = buf;
- a.aio_lio_opcode = opcode as libc::c_int;
+ a.0.aio_offset = offs;
+ a.0.aio_nbytes = len;
+ a.0.aio_buf = buf;
+ a.0.aio_lio_opcode = opcode as libc::c_int;
- AioCb {
+ Box::pin(AioCb {
aiocb: a,
mutable: true,
in_progress: false,
- buffer: Buffer::None
- }
+ _buffer: PhantomData,
+ _pin: std::marker::PhantomPinned,
+ })
}
/// Constructs a new `AioCb` from a raw pointer.
///
/// Unlike `from_slice`, this method returns a structure suitable for
/// placement on the heap. Due to its unsafety, this method is not
- /// recommended. It is most useful when heap allocation is required but for
- /// some reason the data cannot be wrapped in a `struct` that implements
- /// `Borrow<[u8]>`
+ /// recommended. It is most useful when heap allocation is required.
///
/// # Parameters
///
@@ -597,24 +337,49 @@
pub unsafe fn from_ptr(fd: RawFd, offs: off_t,
buf: *const c_void, len: usize,
prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb<'a> {
+ opcode: LioOpcode) -> Pin<Box<AioCb<'a>>> {
let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = offs;
- a.aio_nbytes = len;
+ a.0.aio_offset = offs;
+ a.0.aio_nbytes = len;
// casting a const ptr to a mutable ptr here is ok, because we set the
// AioCb's mutable field to false
- a.aio_buf = buf as *mut c_void;
- a.aio_lio_opcode = opcode as libc::c_int;
+ a.0.aio_buf = buf as *mut c_void;
+ a.0.aio_lio_opcode = opcode as libc::c_int;
+
+ Box::pin(AioCb {
+ aiocb: a,
+ mutable: false,
+ in_progress: false,
+ _buffer: PhantomData,
+ _pin: std::marker::PhantomPinned
+ })
+ }
+
+ // Private helper
+ fn from_slice_unpinned(fd: RawFd, offs: off_t, buf: &'a [u8],
+ prio: libc::c_int, sigev_notify: SigevNotify,
+ opcode: LioOpcode) -> AioCb
+ {
+ let mut a = AioCb::common_init(fd, prio, sigev_notify);
+ a.0.aio_offset = offs;
+ a.0.aio_nbytes = buf.len() as size_t;
+ // casting an immutable buffer to a mutable pointer looks unsafe,
+ // but technically its only unsafe to dereference it, not to create
+ // it.
+ a.0.aio_buf = buf.as_ptr() as *mut c_void;
+ assert!(opcode != LioOpcode::LIO_READ, "Can't read into an immutable buffer");
+ a.0.aio_lio_opcode = opcode as libc::c_int;
AioCb {
aiocb: a,
mutable: false,
in_progress: false,
- buffer: Buffer::None
+ _buffer: PhantomData,
+ _pin: std::marker::PhantomPinned
}
}
- /// Like `from_mut_slice`, but works on constant slices rather than
+ /// Like [`from_mut_slice`], but works on constant slices rather than
/// mutable slices.
///
/// An `AioCb` created this way cannot be used with `read`, and its
@@ -657,27 +422,14 @@
// AioCb, and they must all be of the same type.
pub fn from_slice(fd: RawFd, offs: off_t, buf: &'a [u8],
prio: libc::c_int, sigev_notify: SigevNotify,
- opcode: LioOpcode) -> AioCb {
- let mut a = AioCb::common_init(fd, prio, sigev_notify);
- a.aio_offset = offs;
- a.aio_nbytes = buf.len() as size_t;
- // casting an immutable buffer to a mutable pointer looks unsafe,
- // but technically its only unsafe to dereference it, not to create
- // it.
- a.aio_buf = buf.as_ptr() as *mut c_void;
- assert!(opcode != LioOpcode::LIO_READ, "Can't read into an immutable buffer");
- a.aio_lio_opcode = opcode as libc::c_int;
-
- AioCb {
- aiocb: a,
- mutable: false,
- in_progress: false,
- buffer: Buffer::None,
- }
+ opcode: LioOpcode) -> Pin<Box<AioCb>>
+ {
+ Box::pin(AioCb::from_slice_unpinned(fd, offs, buf, prio, sigev_notify,
+ opcode))
}
fn common_init(fd: RawFd, prio: libc::c_int,
- sigev_notify: SigevNotify) -> libc::aiocb {
+ sigev_notify: SigevNotify) -> LibcAiocb {
// Use mem::zeroed instead of explicitly zeroing each field, because the
// number and name of reserved fields is OS-dependent. On some OSes,
// some reserved fields are used the kernel for state, and must be
@@ -686,12 +438,18 @@
a.aio_fildes = fd;
a.aio_reqprio = prio;
a.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
- a
+ LibcAiocb(a)
}
/// Update the notification settings for an existing `aiocb`
- pub fn set_sigev_notify(&mut self, sigev_notify: SigevNotify) {
- self.aiocb.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
+ pub fn set_sigev_notify(self: &mut Pin<Box<Self>>,
+ sigev_notify: SigevNotify)
+ {
+ // Safe because we don't move any of the data
+ let selfp = unsafe {
+ self.as_mut().get_unchecked_mut()
+ };
+ selfp.aiocb.0.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
}
/// Cancels an outstanding AIO request.
@@ -740,9 +498,13 @@
///
/// # References
///
- /// [aio_cancel](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
- pub fn cancel(&mut self) -> Result<AioCancelStat> {
- match unsafe { libc::aio_cancel(self.aiocb.aio_fildes, &mut self.aiocb) } {
+ /// [aio_cancel](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
+ pub fn cancel(self: &mut Pin<Box<Self>>) -> Result<AioCancelStat> {
+ let r = unsafe {
+ let selfp = self.as_mut().get_unchecked_mut();
+ libc::aio_cancel(selfp.aiocb.0.aio_fildes, &mut selfp.aiocb.0)
+ };
+ match r {
libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
@@ -751,6 +513,18 @@
}
}
+ fn error_unpinned(&mut self) -> Result<()> {
+ let r = unsafe {
+ libc::aio_error(&mut self.aiocb.0 as *mut libc::aiocb)
+ };
+ match r {
+ 0 => Ok(()),
+ num if num > 0 => Err(Error::from_errno(Errno::from_i32(num))),
+ -1 => Err(Error::last()),
+ num => panic!("unknown aio_error return value {:?}", num)
+ }
+ }
+
/// Retrieve error status of an asynchronous operation.
///
/// If the request has not yet completed, returns `EINPROGRESS`. Otherwise,
@@ -788,28 +562,31 @@
///
/// # References
///
- /// [aio_error](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_error.html)
- pub fn error(&mut self) -> Result<()> {
- match unsafe { libc::aio_error(&mut self.aiocb as *mut libc::aiocb) } {
- 0 => Ok(()),
- num if num > 0 => Err(Error::from_errno(Errno::from_i32(num))),
- -1 => Err(Error::last()),
- num => panic!("unknown aio_error return value {:?}", num)
- }
+ /// [aio_error](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_error.html)
+ pub fn error(self: &mut Pin<Box<Self>>) -> Result<()> {
+ // Safe because error_unpinned doesn't move the data
+ let selfp = unsafe {
+ self.as_mut().get_unchecked_mut()
+ };
+ selfp.error_unpinned()
}
/// An asynchronous version of `fsync(2)`.
///
/// # References
///
- /// [aio_fsync](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_fsync.html)
- pub fn fsync(&mut self, mode: AioFsyncMode) -> Result<()> {
- let p: *mut libc::aiocb = &mut self.aiocb;
- Errno::result(unsafe {
+ /// [aio_fsync](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_fsync.html)
+ pub fn fsync(self: &mut Pin<Box<Self>>, mode: AioFsyncMode) -> Result<()> {
+ // Safe because we don't move the libc::aiocb
+ unsafe {
+ let selfp = self.as_mut().get_unchecked_mut();
+ Errno::result({
+ let p: *mut libc::aiocb = &mut selfp.aiocb.0;
libc::aio_fsync(mode as libc::c_int, p)
- }).map(|_| {
- self.in_progress = true;
- })
+ }).map(|_| {
+ selfp.in_progress = true;
+ })
+ }
}
/// Returns the `aiocb`'s `LioOpcode` field
@@ -817,7 +594,7 @@
/// If the value cannot be represented as an `LioOpcode`, returns `None`
/// instead.
pub fn lio_opcode(&self) -> Option<LioOpcode> {
- match self.aiocb.aio_lio_opcode {
+ match self.aiocb.0.aio_lio_opcode {
libc::LIO_READ => Some(LioOpcode::LIO_READ),
libc::LIO_WRITE => Some(LioOpcode::LIO_WRITE),
libc::LIO_NOP => Some(LioOpcode::LIO_NOP),
@@ -831,37 +608,49 @@
/// number of bytes actually read or written by a completed operation, use
/// `aio_return` instead.
pub fn nbytes(&self) -> usize {
- self.aiocb.aio_nbytes
+ self.aiocb.0.aio_nbytes
}
/// Returns the file offset stored in the `AioCb`
pub fn offset(&self) -> off_t {
- self.aiocb.aio_offset
+ self.aiocb.0.aio_offset
}
/// Returns the priority of the `AioCb`
pub fn priority(&self) -> libc::c_int {
- self.aiocb.aio_reqprio
+ self.aiocb.0.aio_reqprio
}
/// Asynchronously reads from a file descriptor into a buffer
///
/// # References
///
- /// [aio_read](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_read.html)
- pub fn read(&mut self) -> Result<()> {
+ /// [aio_read](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_read.html)
+ pub fn read(self: &mut Pin<Box<Self>>) -> Result<()> {
assert!(self.mutable, "Can't read into an immutable buffer");
- let p: *mut libc::aiocb = &mut self.aiocb;
- Errno::result(unsafe {
- libc::aio_read(p)
+ // Safe because we don't move anything
+ let selfp = unsafe {
+ self.as_mut().get_unchecked_mut()
+ };
+ Errno::result({
+ let p: *mut libc::aiocb = &mut selfp.aiocb.0;
+ unsafe { libc::aio_read(p) }
}).map(|_| {
- self.in_progress = true;
+ selfp.in_progress = true;
})
}
/// Returns the `SigEvent` stored in the `AioCb`
pub fn sigevent(&self) -> SigEvent {
- SigEvent::from(&self.aiocb.aio_sigevent)
+ SigEvent::from(&self.aiocb.0.aio_sigevent)
+ }
+
+ fn aio_return_unpinned(&mut self) -> Result<isize> {
+ unsafe {
+ let p: *mut libc::aiocb = &mut self.aiocb.0;
+ self.in_progress = false;
+ Errno::result(libc::aio_return(p))
+ }
}
/// Retrieve return status of an asynchronous operation.
@@ -872,28 +661,33 @@
///
/// # References
///
- /// [aio_return](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html)
+ /// [aio_return](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html)
// Note: this should be just `return`, but that's a reserved word
- pub fn aio_return(&mut self) -> Result<isize> {
- let p: *mut libc::aiocb = &mut self.aiocb;
- self.in_progress = false;
- Errno::result(unsafe { libc::aio_return(p) })
+ pub fn aio_return(self: &mut Pin<Box<Self>>) -> Result<isize> {
+ // Safe because aio_return_unpinned does not move the data
+ let selfp = unsafe {
+ self.as_mut().get_unchecked_mut()
+ };
+ selfp.aio_return_unpinned()
}
/// Asynchronously writes from a buffer to a file descriptor
///
/// # References
///
- /// [aio_write](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_write.html)
- pub fn write(&mut self) -> Result<()> {
- let p: *mut libc::aiocb = &mut self.aiocb;
- Errno::result(unsafe {
- libc::aio_write(p)
+ /// [aio_write](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_write.html)
+ pub fn write(self: &mut Pin<Box<Self>>) -> Result<()> {
+ // Safe because we don't move anything
+ let selfp = unsafe {
+ self.as_mut().get_unchecked_mut()
+ };
+ Errno::result({
+ let p: *mut libc::aiocb = &mut selfp.aiocb.0;
+ unsafe{ libc::aio_write(p) }
}).map(|_| {
- self.in_progress = true;
+ selfp.in_progress = true;
})
}
-
}
/// Cancels outstanding AIO requests for a given file descriptor.
@@ -935,7 +729,7 @@
///
/// # References
///
-/// [`aio_cancel`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
+/// [`aio_cancel`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> {
match unsafe { libc::aio_cancel(fd, null_mut()) } {
libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
@@ -970,15 +764,15 @@
/// SigevNotify::SigevNone,
/// LioOpcode::LIO_NOP);
/// aiocb.write().unwrap();
-/// aio_suspend(&[&aiocb], None).expect("aio_suspend failed");
+/// aio_suspend(&[aiocb.as_ref()], None).expect("aio_suspend failed");
/// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
/// # }
/// ```
/// # References
///
-/// [`aio_suspend`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_suspend.html)
-pub fn aio_suspend(list: &[&AioCb], timeout: Option<TimeSpec>) -> Result<()> {
- let plist = list as *const [&AioCb] as *const [*const libc::aiocb];
+/// [`aio_suspend`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_suspend.html)
+pub fn aio_suspend(list: &[Pin<&AioCb>], timeout: Option<TimeSpec>) -> Result<()> {
+ let plist = list as *const [Pin<&AioCb>] as *const [*const libc::aiocb];
let p = plist as *const *const libc::aiocb;
let timep = match timeout {
None => null::<libc::timespec>(),
@@ -992,7 +786,7 @@
impl<'a> Debug for AioCb<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("AioCb")
- .field("aiocb", &self.aiocb)
+ .field("aiocb", &self.aiocb.0)
.field("mutable", &self.mutable)
.field("in_progress", &self.in_progress)
.finish()
@@ -1018,7 +812,9 @@
///
/// [`AioCb`]: struct.AioCb.html
/// [`listio`]: #method.listio
- pub aiocbs: Vec<AioCb<'a>>,
+ // Their locations in memory must be fixed once they are passed to the
+ // kernel. So this field must be non-public so the user can't swap.
+ aiocbs: Box<[AioCb<'a>]>,
/// The actual list passed to `libc::lio_listio`.
///
@@ -1032,15 +828,23 @@
results: Vec<Option<Result<isize>>>
}
+/// LioCb can't automatically impl Send and Sync just because of the raw
+/// pointers in list. But that's stupid. There's no reason that raw pointers
+/// should automatically be non-Send
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+unsafe impl<'a> Send for LioCb<'a> {}
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+unsafe impl<'a> Sync for LioCb<'a> {}
+
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
impl<'a> LioCb<'a> {
- /// Initialize an empty `LioCb`
- pub fn with_capacity(capacity: usize) -> LioCb<'a> {
- LioCb {
- aiocbs: Vec::with_capacity(capacity),
- list: Vec::with_capacity(capacity),
- results: Vec::with_capacity(capacity)
- }
+ pub fn is_empty(&self) -> bool {
+ self.aiocbs.is_empty()
+ }
+
+ /// Return the number of individual [`AioCb`]s contained.
+ pub fn len(&self) -> usize {
+ self.aiocbs.len()
}
/// Submits multiple asynchronous I/O requests with a single system call.
@@ -1069,13 +873,15 @@
/// # fn main() {
/// const WBUF: &[u8] = b"abcdef123456";
/// let mut f = tempfile().unwrap();
- /// let mut liocb = LioCb::with_capacity(1);
- /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
- /// 2, //offset
- /// WBUF,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_WRITE));
+ /// let mut liocb = LioCbBuilder::with_capacity(1)
+ /// .emplace_slice(
+ /// f.as_raw_fd(),
+ /// 2, //offset
+ /// WBUF,
+ /// 0, //priority
+ /// SigevNotify::SigevNone,
+ /// LioOpcode::LIO_WRITE
+ /// ).finish();
/// liocb.listio(LioMode::LIO_WAIT,
/// SigevNotify::SigevNone).unwrap();
/// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
@@ -1084,7 +890,7 @@
///
/// # References
///
- /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
+ /// [`lio_listio`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
///
/// [`aio_suspend`]: fn.aio_suspend.html
/// [`AioCb::error`]: struct.AioCb.html#method.error
@@ -1093,7 +899,7 @@
let sigev = SigEvent::new(sigev_notify);
let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
self.list.clear();
- for a in &mut self.aiocbs {
+ for a in &mut self.aiocbs.iter_mut() {
a.in_progress = true;
self.list.push(a as *mut AioCb<'a>
as *mut libc::aiocb);
@@ -1127,13 +933,15 @@
/// # fn main() {
/// const WBUF: &[u8] = b"abcdef123456";
/// let mut f = tempfile().unwrap();
- /// let mut liocb = LioCb::with_capacity(1);
- /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
- /// 2, //offset
- /// WBUF,
- /// 0, //priority
- /// SigevNotify::SigevNone,
- /// LioOpcode::LIO_WRITE));
+ /// let mut liocb = LioCbBuilder::with_capacity(1)
+ /// .emplace_slice(
+ /// f.as_raw_fd(),
+ /// 2, //offset
+ /// WBUF,
+ /// 0, //priority
+ /// SigevNotify::SigevNone,
+ /// LioOpcode::LIO_WRITE
+ /// ).finish();
/// let mut err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
/// while err == Err(Error::Sys(Errno::EIO)) ||
/// err == Err(Error::Sys(Errno::EAGAIN)) {
@@ -1146,9 +954,9 @@
///
/// # References
///
- /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
+ /// [`lio_listio`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
///
- /// [`lio_listio`]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html
+ /// [`lio_listio`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html
/// [`LioCb::aio_return`]: struct.LioCb.html#method.aio_return
// Note: the addresses of any EINPROGRESS or EOK aiocbs _must_ not be
// changed by this method, because the kernel relies on their addresses
@@ -1170,10 +978,10 @@
// Already collected final status for this operation
continue;
}
- match a.error() {
+ match a.error_unpinned() {
Ok(()) => {
// aiocb is complete; collect its status and don't resubmit
- self.results[i] = Some(a.aio_return());
+ self.results[i] = Some(a.aio_return_unpinned());
},
Err(Error::Sys(Errno::EAGAIN)) => {
self.list.push(a as *mut AioCb<'a> as *mut libc::aiocb);
@@ -1202,7 +1010,7 @@
/// [`LioCb::listio_resubmit`]: #method.listio_resubmit
pub fn aio_return(&mut self, i: usize) -> Result<isize> {
if i >= self.results.len() || self.results[i].is_none() {
- self.aiocbs[i].aio_return()
+ self.aiocbs[i].aio_return_unpinned()
} else {
self.results[i].unwrap()
}
@@ -1218,7 +1026,7 @@
/// [`LioCb::listio_resubmit`]: #method.listio_resubmit
pub fn error(&mut self, i: usize) -> Result<()> {
if i >= self.results.len() || self.results[i].is_none() {
- self.aiocbs[i].error()
+ self.aiocbs[i].error_unpinned()
} else {
Ok(())
}
@@ -1234,13 +1042,93 @@
}
}
+/// Used to construct `LioCb`
+// This must be a separate class from LioCb due to pinning constraints. LioCb
+// must use a boxed slice of AioCbs so they will have stable storage, but
+// LioCbBuilder must use a Vec to make construction possible when the final size
+// is unknown.
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-impl<'a> From<Vec<AioCb<'a>>> for LioCb<'a> {
- fn from(src: Vec<AioCb<'a>>) -> LioCb<'a> {
- LioCb {
- list: Vec::with_capacity(src.capacity()),
- results: Vec::with_capacity(src.capacity()),
- aiocbs: src,
+#[derive(Debug)]
+pub struct LioCbBuilder<'a> {
+ /// A collection of [`AioCb`]s.
+ ///
+ /// [`AioCb`]: struct.AioCb.html
+ pub aiocbs: Vec<AioCb<'a>>,
+}
+
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+impl<'a> LioCbBuilder<'a> {
+ /// Initialize an empty `LioCb`
+ pub fn with_capacity(capacity: usize) -> LioCbBuilder<'a> {
+ LioCbBuilder {
+ aiocbs: Vec::with_capacity(capacity),
}
}
+
+ /// Add a new operation on an immutable slice to the [`LioCb`] under
+ /// construction.
+ ///
+ /// Arguments are the same as for [`AioCb::from_slice`]
+ ///
+ /// [`LioCb`]: struct.LioCb.html
+ /// [`AioCb::from_slice`]: struct.AioCb.html#method.from_slice
+ pub fn emplace_slice(mut self, fd: RawFd, offs: off_t, buf: &'a [u8],
+ prio: libc::c_int, sigev_notify: SigevNotify,
+ opcode: LioOpcode) -> Self
+ {
+ self.aiocbs.push(AioCb::from_slice_unpinned(fd, offs, buf, prio,
+ sigev_notify, opcode));
+ self
+ }
+
+ /// Add a new operation on a mutable slice to the [`LioCb`] under
+ /// construction.
+ ///
+ /// Arguments are the same as for [`AioCb::from_mut_slice`]
+ ///
+ /// [`LioCb`]: struct.LioCb.html
+ /// [`AioCb::from_mut_slice`]: struct.AioCb.html#method.from_mut_slice
+ pub fn emplace_mut_slice(mut self, fd: RawFd, offs: off_t,
+ buf: &'a mut [u8], prio: libc::c_int,
+ sigev_notify: SigevNotify, opcode: LioOpcode)
+ -> Self
+ {
+ self.aiocbs.push(AioCb::from_mut_slice_unpinned(fd, offs, buf, prio,
+ sigev_notify, opcode));
+ self
+ }
+
+ /// Finalize this [`LioCb`].
+ ///
+ /// Afterwards it will be possible to issue the operations with
+ /// [`LioCb::listio`]. Conversely, it will no longer be possible to add new
+ /// operations with [`LioCb::emplace_slice`] or
+ /// [`LioCb::emplace_mut_slice`].
+ ///
+ /// [`LioCb::listio`]: struct.LioCb.html#method.listio
+ /// [`LioCb::from_mut_slice`]: struct.LioCb.html#method.from_mut_slice
+ /// [`LioCb::from_slice`]: struct.LioCb.html#method.from_slice
+ pub fn finish(self) -> LioCb<'a> {
+ let len = self.aiocbs.len();
+ LioCb {
+ aiocbs: self.aiocbs.into(),
+ list: Vec::with_capacity(len),
+ results: Vec::with_capacity(len)
+ }
+ }
+}
+
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+#[cfg(test)]
+mod t {
+ use super::*;
+
+ // It's important that `LioCb` be `UnPin`. The tokio-file crate relies on
+ // it.
+ #[test]
+ fn liocb_is_unpin() {
+ use assert_impl::assert_impl;
+
+ assert_impl!(Unpin: LioCb);
+ }
}
diff --git a/src/sys/inotify.rs b/src/sys/inotify.rs
index 4880a4a..3f5ae22 100644
--- a/src/sys/inotify.rs
+++ b/src/sys/inotify.rs
@@ -2,8 +2,8 @@
//!
//! Inotify is a Linux-only API to monitor filesystems events.
//!
-//! For more documentation, please read [inotify(7)](http://man7.org/linux/man-pages/man7/inotify.7.html).
-//!
+//! For more documentation, please read [inotify(7)](https://man7.org/linux/man-pages/man7/inotify.7.html).
+//!
//! # Examples
//!
//! Monitor all events happening in directory "test":
@@ -86,7 +86,7 @@
/// This object is returned when you create a new watch on an inotify instance.
/// It is then returned as part of an event once triggered. It allows you to
-/// know which watch triggered which event.
+/// know which watch triggered which event.
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct WatchDescriptor {
wd: i32
@@ -94,18 +94,18 @@
/// A single inotify event.
///
-/// For more documentation see, [inotify(7)](http://man7.org/linux/man-pages/man7/inotify.7.html).
+/// For more documentation see, [inotify(7)](https://man7.org/linux/man-pages/man7/inotify.7.html).
#[derive(Debug)]
pub struct InotifyEvent {
/// Watch descriptor. This field corresponds to the watch descriptor you
/// were issued when calling add_watch. It allows you to know which watch
- /// this event comes from.
+ /// this event comes from.
pub wd: WatchDescriptor,
/// Event mask. This field is a bitfield describing the exact event that
/// occured.
pub mask: AddWatchFlags,
/// This cookie is a number that allows you to connect related events. For
- /// now only IN_MOVED_FROM and IN_MOVED_TO can be connected.
+ /// now only IN_MOVED_FROM and IN_MOVED_TO can be connected.
pub cookie: u32,
/// Filename. This field exists only if the event was triggered for a file
/// inside the watched directory.
@@ -117,7 +117,7 @@
///
/// Returns a Result containing an inotify instance.
///
- /// For more information see, [inotify_init(2)](http://man7.org/linux/man-pages/man2/inotify_init.2.html).
+ /// For more information see, [inotify_init(2)](https://man7.org/linux/man-pages/man2/inotify_init.2.html).
pub fn init(flags: InitFlags) -> Result<Inotify> {
let res = Errno::result(unsafe {
libc::inotify_init1(flags.bits())
@@ -126,14 +126,14 @@
res.map(|fd| Inotify { fd })
}
- /// Adds a new watch on the target file or directory.
+ /// Adds a new watch on the target file or directory.
///
- /// Returns a watch descriptor. This is not a File Descriptor!
+ /// Returns a watch descriptor. This is not a File Descriptor!
///
- /// For more information see, [inotify_add_watch(2)](http://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
+ /// For more information see, [inotify_add_watch(2)](https://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
pub fn add_watch<P: ?Sized + NixPath>(self,
path: &P,
- mask: AddWatchFlags)
+ mask: AddWatchFlags)
-> Result<WatchDescriptor>
{
let res = path.with_nix_path(|cstr| {
@@ -150,7 +150,7 @@
///
/// Returns an EINVAL error if the watch descriptor is invalid.
///
- /// For more information see, [inotify_rm_watch(2)](http://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
+ /// For more information see, [inotify_rm_watch(2)](https://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
#[cfg(target_os = "linux")]
pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd) };
@@ -167,8 +167,8 @@
/// Reads a collection of events from the inotify file descriptor. This call
/// can either be blocking or non blocking depending on whether IN_NONBLOCK
- /// was set at initialization.
- ///
+ /// was set at initialization.
+ ///
/// Returns as many events as available. If the call was non blocking and no
/// events could be read then the EAGAIN error is returned.
pub fn read_events(self) -> Result<Vec<InotifyEvent>> {
@@ -194,14 +194,14 @@
let name = match event.len {
0 => None,
_ => {
- let ptr = unsafe {
+ let ptr = unsafe {
buffer
.as_ptr()
.add(offset + header_size)
as *const c_char
};
let cstr = unsafe { CStr::from_ptr(ptr) };
-
+
Some(OsStr::from_bytes(cstr.to_bytes()).to_owned())
}
};
diff --git a/src/sys/ioctl/bsd.rs b/src/sys/ioctl/bsd.rs
index f39c0eb..4ce4d33 100644
--- a/src/sys/ioctl/bsd.rs
+++ b/src/sys/ioctl/bsd.rs
@@ -1,6 +1,12 @@
/// The datatype used for the ioctl number
#[doc(hidden)]
+#[cfg(not(target_os = "illumos"))]
pub type ioctl_num_type = ::libc::c_ulong;
+
+#[doc(hidden)]
+#[cfg(target_os = "illumos")]
+pub type ioctl_num_type = ::libc::c_int;
+
/// The datatype used for the 3rd argument
#[doc(hidden)]
pub type ioctl_param_type = ::libc::c_int;
@@ -12,6 +18,7 @@
#[doc(hidden)]
pub const OUT: ioctl_num_type = 0x4000_0000;
#[doc(hidden)]
+ #[allow(overflowing_literals)]
pub const IN: ioctl_num_type = 0x8000_0000;
#[doc(hidden)]
pub const INOUT: ioctl_num_type = IN|OUT;
diff --git a/src/sys/ioctl/mod.rs b/src/sys/ioctl/mod.rs
index 8858a9d..203b7d0 100644
--- a/src/sys/ioctl/mod.rs
+++ b/src/sys/ioctl/mod.rs
@@ -104,7 +104,7 @@
//! respectively. To determine the specific `write_` variant to use you'll need to find
//! what the argument type is supposed to be. If it's an `int`, then `write_int` should be used,
//! otherwise it should be a pointer and `write_ptr` should be used. On Linux the
-//! [`ioctl_list` man page](http://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a
+//! [`ioctl_list` man page](https://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a
//! large number of `ioctl`s and describes their argument data type.
//!
//! Using "bad" `ioctl`s
@@ -232,6 +232,7 @@
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
@@ -241,6 +242,7 @@
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
diff --git a/src/sys/mman.rs b/src/sys/mman.rs
index 63a0779..34c7663 100644
--- a/src/sys/mman.rs
+++ b/src/sys/mman.rs
@@ -372,7 +372,7 @@
/// Set protection of memory mapping.
///
-/// See [`mprotect(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
+/// See [`mprotect(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
/// details.
///
/// # Safety
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index 02edfd7..51f0eed 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -28,6 +28,7 @@
target_os = "redox",
target_os = "macos",
target_os = "netbsd",
+ target_os = "illumos",
target_os = "openbsd"))]
#[macro_use]
pub mod ioctl;
diff --git a/src/sys/pthread.rs b/src/sys/pthread.rs
index a4d9825..f730408 100644
--- a/src/sys/pthread.rs
+++ b/src/sys/pthread.rs
@@ -3,7 +3,7 @@
pub type Pthread = pthread_t;
/// Obtain ID of the calling thread (see
-/// [`pthread_self(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html)
+/// [`pthread_self(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html)
///
/// The thread ID returned by `pthread_self()` is not the same thing as
/// the kernel thread ID returned by a call to `gettid(2)`.
diff --git a/src/sys/ptrace/bsd.rs b/src/sys/ptrace/bsd.rs
index e85afc7..141dfbc 100644
--- a/src/sys/ptrace/bsd.rs
+++ b/src/sys/ptrace/bsd.rs
@@ -133,16 +133,14 @@
/// use nix::unistd::Pid;
/// use nix::sys::signal::Signal;
/// use nix::sys::wait::*;
-/// fn main() {
-/// // If a process changes state to the stopped state because of a SIGUSR1
-/// // signal, this will step the process forward and forward the user
-/// // signal to the stopped process
-/// match waitpid(Pid::from_raw(-1), None) {
-/// Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => {
-/// let _ = step(pid, Signal::SIGUSR1);
-/// }
-/// _ => {},
+/// // If a process changes state to the stopped state because of a SIGUSR1
+/// // signal, this will step the process forward and forward the user
+/// // signal to the stopped process
+/// match waitpid(Pid::from_raw(-1), None) {
+/// Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => {
+/// let _ = step(pid, Signal::SIGUSR1);
/// }
+/// _ => {},
/// }
/// ```
#[cfg(
diff --git a/src/sys/select.rs b/src/sys/select.rs
index a576c7e..5eb6423 100644
--- a/src/sys/select.rs
+++ b/src/sys/select.rs
@@ -50,12 +50,10 @@
///
/// ```
/// # use nix::sys::select::FdSet;
- /// # fn main() {
/// let mut set = FdSet::new();
/// set.insert(4);
/// set.insert(9);
/// assert_eq!(set.highest(), Some(9));
- /// # }
/// ```
///
/// [`select`]: fn.select.html
@@ -64,7 +62,7 @@
}
/// Returns an iterator over the file descriptors in the set.
- ///
+ ///
/// For performance, it takes an optional higher bound: the iterator will
/// not return any elements of the set greater than the given file
/// descriptor.
@@ -155,7 +153,7 @@
///
/// # References
///
-/// [select(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
+/// [select(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
///
/// [`FdSet::highest`]: struct.FdSet.html#method.highest
pub fn select<'a, N, R, W, E, T>(nfds: N,
@@ -221,7 +219,7 @@
///
/// # References
///
-/// [pselect(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html)
+/// [pselect(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html)
///
/// [The new pselect() system call](https://lwn.net/Articles/176911/)
///
diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs
index 84fe2a9..a12c041 100644
--- a/src/sys/sendfile.rs
+++ b/src/sys/sendfile.rs
@@ -18,7 +18,7 @@
///
/// `in_fd` must support `mmap`-like operations and therefore cannot be a socket.
///
-/// For more information, see [the sendfile(2) man page.](http://man7.org/linux/man-pages/man2/sendfile.2.html)
+/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
#[cfg(any(target_os = "android", target_os = "linux"))]
pub fn sendfile(
out_fd: RawFd,
@@ -33,6 +33,32 @@
Errno::result(ret).map(|r| r as usize)
}
+/// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`.
+///
+/// Returns a `Result` with the number of bytes written.
+///
+/// If `offset` is `None`, `sendfile` will begin reading at the current offset of `in_fd`and will
+/// update the offset of `in_fd`. If `offset` is `Some`, `sendfile` will begin at the specified
+/// offset and will not update the offset of `in_fd`. Instead, it will mutate `offset` to point to
+/// the byte after the last byte copied.
+///
+/// `in_fd` must support `mmap`-like operations and therefore cannot be a socket.
+///
+/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
+#[cfg(target_os = "linux")]
+pub fn sendfile64(
+ out_fd: RawFd,
+ in_fd: RawFd,
+ offset: Option<&mut libc::off64_t>,
+ count: usize,
+) -> Result<usize> {
+ let offset = offset
+ .map(|offset| offset as *mut _)
+ .unwrap_or(ptr::null_mut());
+ let ret = unsafe { libc::sendfile64(out_fd, in_fd, offset, count) };
+ Errno::result(ret).map(|r| r as usize)
+}
+
cfg_if! {
if #[cfg(any(target_os = "freebsd",
target_os = "ios",
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index 2f8b5fa..bf3f762 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -1,5 +1,5 @@
// Portions of this file are Copyright 2014 The Rust Project Developers.
-// See http://rust-lang.org/COPYRIGHT.
+// See https://www.rust-lang.org/policies/licenses.
///! Operating system signals.
@@ -619,7 +619,7 @@
Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
}
-/// Signal management (see [signal(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
+/// Signal management (see [signal(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
///
/// Installs `handler` for the given `signal`, returning the previous signal
/// handler. `signal` should only be used following another call to `signal` or
@@ -724,8 +724,8 @@
///
/// If both `set` and `oldset` is None, this function is a no-op.
///
-/// For more information, visit the [`pthread_sigmask`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html),
-/// or [`sigprocmask`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
+/// For more information, visit the [`pthread_sigmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html),
+/// or [`sigprocmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
pub fn pthread_sigmask(how: SigmaskHow,
set: Option<&SigSet>,
oldset: Option<&mut SigSet>) -> Result<()>
@@ -736,7 +736,7 @@
/// Examine and change blocked signals.
///
/// For more informations see the [`sigprocmask` man
-/// pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
+/// pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
if set.is_none() && oldset.is_none() {
return Ok(())
@@ -765,7 +765,7 @@
}
/// Send a signal to a process group [(see
-/// killpg(3))](http://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
+/// killpg(3))](https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
///
/// If `pgrp` less then or equal 1, the behavior is platform-specific.
/// If `signal` is `None`, `killpg` will only preform error checking and won't
@@ -850,10 +850,10 @@
/// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or
/// `SIGEV_SIGNAL`. That field is part of a union that shares space with the
/// more genuinely useful `sigev_notify_thread_id`
+ // Allow invalid_value warning on Fuchsia only.
+ // See https://github.com/nix-rust/nix/issues/1441
+ #[cfg_attr(target_os = "fuchsia", allow(invalid_value))]
pub fn new(sigev_notify: SigevNotify) -> SigEvent {
- // NB: This uses MaybeUninit rather than mem::zeroed because libc::sigevent contains a
- // function pointer on Fuchsia as of https://github.com/rust-lang/libc/commit/2f59370,
- // and function pointers must not be null.
let mut sev = unsafe { mem::MaybeUninit::<libc::sigevent>::zeroed().assume_init() };
sev.sigev_notify = match sigev_notify {
SigevNotify::SigevNone => libc::SIGEV_NONE,
diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs
index c43b450..1e162cf 100644
--- a/src/sys/signalfd.rs
+++ b/src/sys/signalfd.rs
@@ -46,7 +46,7 @@
/// A signal must be blocked on every thread in a process, otherwise it won't be visible from
/// signalfd (the default handler will be invoked instead).
///
-/// See [the signalfd man page for more information](http://man7.org/linux/man-pages/man2/signalfd.2.html)
+/// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html)
pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
unsafe {
Errno::result(libc::signalfd(fd as libc::c_int, mask.as_ref(), flags.bits()))
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index 2299c57..6a0bc9a 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -1,6 +1,7 @@
use super::sa_family_t;
use crate::{Error, Result, NixPath};
use crate::errno::Errno;
+use memoffset::offset_of;
use std::{fmt, mem, net, ptr, slice};
use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
@@ -20,6 +21,7 @@
target_os = "ios",
target_os = "linux",
target_os = "macos",
+ target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd",
target_os = "fuchsia"))]
@@ -32,17 +34,21 @@
#[repr(i32)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum AddressFamily {
- /// Local communication (see [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html))
+ /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html))
Unix = libc::AF_UNIX,
- /// IPv4 Internet protocols (see [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html))
+ /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html))
Inet = libc::AF_INET,
- /// IPv6 Internet protocols (see [`ipv6(7)`](http://man7.org/linux/man-pages/man7/ipv6.7.html))
+ /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html))
Inet6 = libc::AF_INET6,
- /// Kernel user interface device (see [`netlink(7)`](http://man7.org/linux/man-pages/man7/netlink.7.html))
+ /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
#[cfg(any(target_os = "android", target_os = "linux"))]
Netlink = libc::AF_NETLINK,
- /// Low level packet interface (see [`packet(7)`](http://man7.org/linux/man-pages/man7/packet.7.html))
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
+ /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
+ #[cfg(any(target_os = "android",
+ target_os = "linux",
+ target_os = "illumos",
+ target_os = "fuchsia",
+ target_os = "solaris"))]
Packet = libc::AF_PACKET,
/// KEXT Controls and Notifications
#[cfg(any(target_os = "ios", target_os = "macos"))]
@@ -61,7 +67,7 @@
/// Access to raw ATM PVCs
#[cfg(any(target_os = "android", target_os = "linux"))]
AtmPvc = libc::AF_ATMPVC,
- /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](http://man7.org/linux/man-pages/man7/x25.7.html))
+ /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html))
#[cfg(any(target_os = "android", target_os = "linux"))]
X25 = libc::AF_X25,
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -98,12 +104,16 @@
Can = libc::AF_CAN,
#[cfg(any(target_os = "android", target_os = "linux"))]
Tipc = libc::AF_TIPC,
- #[cfg(not(any(target_os = "ios", target_os = "macos")))]
+ #[cfg(not(any(target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "solaris")))]
Bluetooth = libc::AF_BLUETOOTH,
#[cfg(any(target_os = "android", target_os = "linux"))]
Iucv = libc::AF_IUCV,
#[cfg(any(target_os = "android", target_os = "linux"))]
RxRpc = libc::AF_RXRPC,
+ #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
Isdn = libc::AF_ISDN,
#[cfg(any(target_os = "android", target_os = "linux"))]
Phonet = libc::AF_PHONET,
@@ -190,6 +200,7 @@
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
+ target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd"))]
Link = libc::AF_LINK,
@@ -214,7 +225,7 @@
target_os = "netbsd",
target_os = "openbsd"))]
Natm = libc::AF_NATM,
- /// Unspecified address family, (see [`getaddrinfo(3)`](http://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
+ /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
#[cfg(any(target_os = "android", target_os = "linux"))]
Unspec = libc::AF_UNSPEC,
}
@@ -241,6 +252,7 @@
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
+ target_os = "illumos",
target_os = "openbsd"))]
libc::AF_LINK => Some(AddressFamily::Link),
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -645,6 +657,7 @@
target_os = "ios",
target_os = "linux",
target_os = "macos",
+ target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd"))]
Link(LinkAddr),
@@ -699,6 +712,7 @@
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
+ target_os = "illumos",
target_os = "openbsd"))]
SockAddr::Link(..) => AddressFamily::Link,
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -744,6 +758,7 @@
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
+ target_os = "illumos",
target_os = "openbsd"))]
Some(AddressFamily::Link) => {
let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
@@ -830,6 +845,7 @@
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
+ target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd"))]
SockAddr::Link(LinkAddr(ref addr)) => (
@@ -869,6 +885,7 @@
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
+ target_os = "illumos",
target_os = "openbsd"))]
SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -1118,6 +1135,7 @@
target_os = "freebsd",
target_os = "ios",
target_os = "macos",
+ target_os = "illumos",
target_os = "netbsd",
target_os = "openbsd"))]
mod datalink {
@@ -1129,6 +1147,7 @@
impl LinkAddr {
/// Total length of sockaddr
+ #[cfg(not(target_os = "illumos"))]
pub fn len(&self) -> usize {
self.0.sdl_len as usize
}
@@ -1280,6 +1299,7 @@
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
+ target_os = "illumos",
target_os = "openbsd"))]
use super::*;
@@ -1324,6 +1344,28 @@
};
}
+ #[cfg(target_os = "illumos")]
+ #[test]
+ fn test_illumos_tap_datalink_addr() {
+ let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
+ let ptr = bytes.as_ptr();
+ let sa = ptr as *const libc::sockaddr;
+ let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
+
+ assert!(_sock_addr.is_some());
+
+ let sock_addr = _sock_addr.unwrap();
+
+ assert_eq!(sock_addr.family(), AddressFamily::Link);
+
+ match sock_addr {
+ SockAddr::Link(ether_addr) => {
+ assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
+ },
+ _ => { unreachable!() }
+ };
+ }
+
#[cfg(any(target_os = "android", target_os = "linux"))]
#[test]
fn test_abstract_sun_path() {
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index 11ed329..6907046 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -1,12 +1,15 @@
//! Socket interface functions
//!
-//! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
+//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
use cfg_if::cfg_if;
use crate::{Error, Result, errno::Errno};
use libc::{self, c_void, c_int, iovec, socklen_t, size_t,
CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN};
+use memoffset::offset_of;
use std::{mem, ptr, slice};
use std::os::unix::io::RawFd;
+#[cfg(all(target_os = "linux"))]
+use crate::sys::time::TimeSpec;
use crate::sys::time::TimeVal;
use crate::sys::uio::IoVec;
@@ -19,6 +22,7 @@
*
*/
+#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
pub use self::addr::{
AddressFamily,
SockAddr,
@@ -29,6 +33,17 @@
Ipv6Addr,
LinkAddr,
};
+#[cfg(any(target_os = "illumos", target_os = "solaris"))]
+pub use self::addr::{
+ AddressFamily,
+ SockAddr,
+ InetAddr,
+ UnixAddr,
+ IpAddr,
+ Ipv4Addr,
+ Ipv6Addr,
+};
+
#[cfg(any(target_os = "android", target_os = "linux"))]
pub use crate::sys::socket::addr::netlink::NetlinkAddr;
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -80,9 +95,9 @@
#[repr(i32)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum SockProtocol {
- /// TCP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
+ /// TCP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
Tcp = libc::IPPROTO_TCP,
- /// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
+ /// UDP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
Udp = libc::IPPROTO_UDP,
/// Allows applications and other KEXTs to be notified when certain kernel events occur
/// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
@@ -159,6 +174,7 @@
#[cfg(any(target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"))]
@@ -167,6 +183,7 @@
#[cfg(any(target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"))]
@@ -202,7 +219,7 @@
/// (via the [`fcntl`](../../fcntl/fn.fcntl.html)
/// `F_SETFL` operation), but differs in that `MSG_DONTWAIT` is a per-
/// call option, whereas `O_NONBLOCK` is a setting on the open file
- /// description (see [open(2)](http://man7.org/linux/man-pages/man2/open.2.html)),
+ /// description (see [open(2)](https://man7.org/linux/man-pages/man2/open.2.html)),
/// which will affect all threads in
/// the calling process and as well as other processes that hold
/// file descriptors referring to the same open file description.
@@ -230,7 +247,7 @@
/// file descriptor using the `SCM_RIGHTS` operation (described in
/// [unix(7)](https://linux.die.net/man/7/unix)).
/// This flag is useful for the same reasons as the `O_CLOEXEC` flag of
- /// [open(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
+ /// [open(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
///
/// Only used in [`recvmsg`](fn.recvmsg.html) function.
#[cfg(any(target_os = "android",
@@ -401,13 +418,11 @@
macro_rules! cmsg_space {
( $( $x:ty ),* ) => {
{
- use nix::sys::socket::{c_uint, CMSG_SPACE};
- use std::mem;
let mut space = 0;
$(
// CMSG_SPACE is always safe
space += unsafe {
- CMSG_SPACE(mem::size_of::<$x>() as c_uint)
+ $crate::sys::socket::CMSG_SPACE(::std::mem::size_of::<$x>() as $crate::sys::socket::c_uint)
} as usize;
)*
Vec::<u8>::with_capacity(space)
@@ -467,7 +482,7 @@
/// A type-safe wrapper around a single control message, as used with
/// [`recvmsg`](#fn.recvmsg).
///
-/// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
+/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
// Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and
// sendmsg. However, on some platforms the messages returned by recvmsg may be
// unaligned. ControlMessageOwned takes those messages by copy, obviating any
@@ -495,6 +510,7 @@
///
/// # Examples
///
+ /// ```
/// # #[macro_use] extern crate nix;
/// # use nix::sys::socket::*;
/// # use nix::sys::uio::IoVec;
@@ -542,6 +558,11 @@
/// # }
/// ```
ScmTimestamp(TimeVal),
+ /// Nanoseconds resolution timestamp
+ ///
+ /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
+ #[cfg(all(target_os = "linux"))]
+ ScmTimestampns(TimeSpec),
#[cfg(any(
target_os = "android",
target_os = "ios",
@@ -633,6 +654,11 @@
let tv: libc::timeval = ptr::read_unaligned(p as *const _);
ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
},
+ #[cfg(all(target_os = "linux"))]
+ (libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => {
+ let ts: libc::timespec = ptr::read_unaligned(p as *const _);
+ ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
+ }
#[cfg(any(
target_os = "android",
target_os = "freebsd",
@@ -684,7 +710,7 @@
},
(_, _) => {
let sl = slice::from_raw_parts(p, len);
- let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(&sl[..]));
+ let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(sl));
ControlMessageOwned::Unknown(ucmsg)
}
}
@@ -695,14 +721,14 @@
/// [`sendmsg`](#fn.sendmsg). More types may be added to this enum; do not
/// exhaustively pattern-match it.
///
-/// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
+/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ControlMessage<'a> {
/// A message of type `SCM_RIGHTS`, containing an array of file
/// descriptors passed between processes.
///
/// See the description in the "Ancillary messages" section of the
- /// [unix(7) man page](http://man7.org/linux/man-pages/man7/unix.7.html).
+ /// [unix(7) man page](https://man7.org/linux/man-pages/man7/unix.7.html).
///
/// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
/// recommended since it causes platform-dependent behaviour: It might
@@ -719,7 +745,7 @@
/// processes are verified by the kernel.
///
/// For further information, please refer to the
- /// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page.
+ /// [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html) man page.
#[cfg(any(target_os = "android", target_os = "linux"))]
ScmCredentials(&'a UnixCredentials),
/// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
@@ -781,7 +807,7 @@
/// Configure the sending addressing and interface for v4
///
/// For further information, please refer to the
- /// [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html) man page.
+ /// [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html) man page.
#[cfg(any(target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -792,7 +818,7 @@
/// Configure the sending addressing and interface for v6
///
/// For further information, please refer to the
- /// [`ipv6(7)`](http://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
+ /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
#[cfg(any(target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -1089,23 +1115,22 @@
let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);
- let mut cmsgs_buffer = vec![0u8; 0];
+ let mut cmsgs_buffers = Vec::<Vec<u8>>::with_capacity(reserve_items);
for d in iter {
- let cmsgs_start = cmsgs_buffer.len();
- let cmsgs_required_capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
- let cmsgs_buffer_need_capacity = cmsgs_start + cmsgs_required_capacity;
- cmsgs_buffer.resize(cmsgs_buffer_need_capacity, 0);
+ let capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
+ let mut cmsgs_buffer = vec![0u8; capacity];
output.push(libc::mmsghdr {
msg_hdr: pack_mhdr_to_send(
- &mut cmsgs_buffer[cmsgs_start..],
+ &mut cmsgs_buffer,
&d.iov,
&d.cmsgs,
d.addr.as_ref()
),
msg_len: 0,
});
+ cmsgs_buffers.push(cmsgs_buffer);
};
let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) };
@@ -1378,7 +1403,7 @@
/// * `flags`: Optional flags passed directly to the operating system.
///
/// # References
-/// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
+/// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
mut cmsg_buffer: Option<&'a mut Vec<u8>>,
flags: MsgFlags) -> Result<RecvMsg<'a>>
@@ -1406,7 +1431,7 @@
/// protocols may exist, in which case a particular protocol must be
/// specified in this manner.
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
let protocol = match protocol.into() {
None => 0,
@@ -1426,7 +1451,7 @@
/// Create a pair of connected sockets
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
flags: SockFlag) -> Result<(RawFd, RawFd)> {
let protocol = match protocol.into() {
@@ -1450,7 +1475,7 @@
/// Listen for connections on a socket
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
let res = unsafe { libc::listen(sockfd, backlog as c_int) };
@@ -1459,7 +1484,7 @@
/// Bind a name to a socket
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
let res = unsafe {
let (ptr, len) = addr.as_ffi_pair();
@@ -1471,7 +1496,7 @@
/// Accept a connection on a socket
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
pub fn accept(sockfd: RawFd) -> Result<RawFd> {
let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
@@ -1480,8 +1505,15 @@
/// Accept a connection on a socket
///
-/// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
-#[cfg(any(target_os = "android",
+/// [Further reading](https://man7.org/linux/man-pages/man2/accept.2.html)
+#[cfg(any(all(
+ target_os = "android",
+ any(
+ target_arch = "aarch64",
+ target_arch = "x86",
+ target_arch = "x86_64"
+ )
+ ),
target_os = "freebsd",
target_os = "linux",
target_os = "openbsd"))]
@@ -1493,7 +1525,7 @@
/// Initiate a connection on a socket
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
let res = unsafe {
let (ptr, len) = addr.as_ffi_pair();
@@ -1506,7 +1538,7 @@
/// Receive data from a connection-oriented socket. Returns the number of
/// bytes read
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
unsafe {
let ret = libc::recv(
@@ -1523,7 +1555,7 @@
/// the number of bytes read and, for connectionless sockets, the socket
/// address of the sender.
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
-> Result<(usize, Option<SockAddr>)>
{
@@ -1549,7 +1581,7 @@
/// Send a message to a socket
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
let ret = unsafe {
let (ptr, len) = addr.as_ffi_pair();
@@ -1561,7 +1593,7 @@
/// Send data to a connection-oriented socket. Returns the number of bytes read
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
let ret = unsafe {
libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
@@ -1596,14 +1628,14 @@
/// Get the current value for the requested socket option
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
opt.get(fd)
}
/// Sets the value for the requested socket option
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
///
/// # Examples
///
@@ -1624,7 +1656,7 @@
/// Get the address of the peer connected to the socket `fd`.
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
unsafe {
let mut addr = mem::MaybeUninit::uninit();
@@ -1644,7 +1676,7 @@
/// Get the current address to which the socket `fd` is bound.
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
unsafe {
let mut addr = mem::MaybeUninit::uninit();
@@ -1704,7 +1736,10 @@
#[cfg(any(target_os = "android", target_os = "linux"))]
libc::AF_PACKET => {
use libc::sockaddr_ll;
- assert_eq!(len as usize, mem::size_of::<sockaddr_ll>());
+ // Apparently the Linux kernel can return smaller sizes when
+ // the value in the last element of sockaddr_ll (`sll_addr`) is
+ // smaller than the declared size of that field
+ assert!(len as usize <= mem::size_of::<sockaddr_ll>());
let sll = unsafe {
*(addr as *const _ as *const sockaddr_ll)
};
@@ -1751,7 +1786,7 @@
/// Shut down part of a full-duplex connection.
///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
unsafe {
use libc::shutdown;
@@ -1765,3 +1800,11 @@
Errno::result(shutdown(df, how)).map(drop)
}
}
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn can_use_cmsg_space() {
+ let _ = cmsg_space!(u8);
+ }
+}
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs
index 5b7b4fe..fe17395 100644
--- a/src/sys/socket/sockopt.rs
+++ b/src/sys/socket/sockopt.rs
@@ -214,6 +214,7 @@
*/
sockopt_impl!(Both, ReuseAddr, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool);
+#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
sockopt_impl!(Both, ReusePort, libc::SOL_SOCKET, libc::SO_REUSEPORT, bool);
sockopt_impl!(Both, TcpNoDelay, libc::IPPROTO_TCP, libc::TCP_NODELAY, bool);
sockopt_impl!(Both, Linger, libc::SOL_SOCKET, libc::SO_LINGER, libc::linger);
@@ -225,10 +226,12 @@
sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest);
} else if #[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "ios",
target_os = "macos",
target_os = "netbsd",
- target_os = "openbsd"))] {
+ target_os = "openbsd",
+ target_os = "solaris"))] {
sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest);
sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest);
}
@@ -269,6 +272,8 @@
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in);
sockopt_impl!(Both, ReceiveTimestamp, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
+#[cfg(all(target_os = "linux"))]
+sockopt_impl!(Both, ReceiveTimestampns, libc::SOL_SOCKET, libc::SO_TIMESTAMPNS, bool);
#[cfg(any(target_os = "android", target_os = "linux"))]
sockopt_impl!(Both, IpTransparent, libc::SOL_IP, libc::IP_TRANSPARENT, bool);
#[cfg(target_os = "openbsd")]
diff --git a/src/sys/stat.rs b/src/sys/stat.rs
index df81a2c..15451e7 100644
--- a/src/sys/stat.rs
+++ b/src/sys/stat.rs
@@ -127,7 +127,7 @@
///
/// # References
///
-/// [fchmod(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
+/// [fchmod(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> {
let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) };
@@ -156,7 +156,7 @@
///
/// # References
///
-/// [fchmodat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
+/// [fchmodat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
#[cfg(not(target_os = "redox"))]
pub fn fchmodat<P: ?Sized + NixPath>(
dirfd: Option<RawFd>,
@@ -190,7 +190,7 @@
///
/// # References
///
-/// [utimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
+/// [utimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
let res = path.with_nix_path(|cstr| unsafe {
@@ -209,7 +209,7 @@
///
/// # References
///
-/// [lutimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
+/// [lutimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
#[cfg(any(target_os = "linux",
target_os = "haiku",
target_os = "ios",
@@ -229,7 +229,7 @@
///
/// # References
///
-/// [futimens(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
+/// [futimens(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
#[inline]
pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> {
let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
@@ -260,7 +260,7 @@
///
/// # References
///
-/// [utimensat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
+/// [utimensat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
#[cfg(not(target_os = "redox"))]
pub fn utimensat<P: ?Sized + NixPath>(
dirfd: Option<RawFd>,
diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs
index 9bea973..508fa8d 100644
--- a/src/sys/statvfs.rs
+++ b/src/sys/statvfs.rs
@@ -1,6 +1,6 @@
//! Get filesystem statistics
//!
-//! See [the man pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
+//! See [the man pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
//! for more details.
use std::mem;
use std::os::unix::io::AsRawFd;
@@ -54,7 +54,7 @@
/// Wrapper around the POSIX `statvfs` struct
///
-/// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
+/// For more information see the [`statvfs(3)` man pages](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Statvfs(libc::statvfs);
diff --git a/src/sys/sysinfo.rs b/src/sys/sysinfo.rs
index 222a2fc..dc943c1 100644
--- a/src/sys/sysinfo.rs
+++ b/src/sys/sysinfo.rs
@@ -71,7 +71,7 @@
/// Returns system information.
///
-/// [See `sysinfo(2)`](http://man7.org/linux/man-pages/man2/sysinfo.2.html).
+/// [See `sysinfo(2)`](https://man7.org/linux/man-pages/man2/sysinfo.2.html).
pub fn sysinfo() -> Result<SysInfo> {
let mut info = mem::MaybeUninit::uninit();
let res = unsafe { libc::sysinfo(info.as_mut_ptr()) };
diff --git a/src/sys/termios.rs b/src/sys/termios.rs
index c30de80..8c3c1cf 100644
--- a/src/sys/termios.rs
+++ b/src/sys/termios.rs
@@ -5,7 +5,7 @@
//! types here or exported directly.
//!
//! If you are unfamiliar with the `termios` API, you should first read the
-//! [API documentation](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html) and
+//! [API documentation](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html) and
//! then come back to understand how `nix` safely wraps it.
//!
//! It should be noted that this API incurs some runtime overhead above the base `libc` definitions.
@@ -299,11 +299,17 @@
target_os = "openbsd"))]
B76800,
B115200,
+ #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ B153600,
B230400,
+ #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ B307200,
#[cfg(any(target_os = "android",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "linux",
- target_os = "netbsd"))]
+ target_os = "netbsd",
+ target_os = "solaris"))]
B460800,
#[cfg(any(target_os = "android", target_os = "linux"))]
B500000,
@@ -311,8 +317,10 @@
B576000,
#[cfg(any(target_os = "android",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "linux",
- target_os = "netbsd"))]
+ target_os = "netbsd",
+ target_os = "solaris"))]
B921600,
#[cfg(any(target_os = "android", target_os = "linux"))]
B1000000,
@@ -354,6 +362,8 @@
target_os = "linux",
target_os = "netbsd"))]
use libc::{B460800, B921600};
+ #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+ use libc::{B153600, B307200, B460800, B921600};
match s {
B0 => Ok(BaudRate::B0),
@@ -398,11 +408,19 @@
target_os = "openbsd"))]
B76800 => Ok(BaudRate::B76800),
B115200 => Ok(BaudRate::B115200),
+ #[cfg(any(target_os = "illumos",
+ target_os = "solaris"))]
+ B153600 => Ok(BaudRate::B153600),
B230400 => Ok(BaudRate::B230400),
+ #[cfg(any(target_os = "illumos",
+ target_os = "solaris"))]
+ B307200 => Ok(BaudRate::B307200),
#[cfg(any(target_os = "android",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "linux",
- target_os = "netbsd"))]
+ target_os = "netbsd",
+ target_os = "solaris"))]
B460800 => Ok(BaudRate::B460800),
#[cfg(any(target_os = "android", target_os = "linux"))]
B500000 => Ok(BaudRate::B500000),
@@ -410,8 +428,10 @@
B576000 => Ok(BaudRate::B576000),
#[cfg(any(target_os = "android",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "linux",
- target_os = "netbsd"))]
+ target_os = "netbsd",
+ target_os = "solaris"))]
B921600 => Ok(BaudRate::B921600),
#[cfg(any(target_os = "android", target_os = "linux"))]
B1000000 => Ok(BaudRate::B1000000),
@@ -502,37 +522,46 @@
VDISCARD,
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "macos",
target_os = "netbsd",
- target_os = "openbsd"))]
+ target_os = "openbsd",
+ target_os = "solaris"))]
VDSUSP,
VEOF,
VEOL,
VEOL2,
VERASE,
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "solaris"))]
VERASE2,
VINTR,
VKILL,
VLNEXT,
- #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
+ #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
+ target_os = "illumos", target_os = "solaris")))]
VMIN,
VQUIT,
VREPRINT,
VSTART,
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
+ target_os = "illumos",
target_os = "macos",
target_os = "netbsd",
- target_os = "openbsd"))]
+ target_os = "openbsd",
+ target_os = "solaris"))]
VSTATUS,
VSTOP,
VSUSP,
#[cfg(target_os = "linux")]
VSWTC,
- #[cfg(target_os = "haiku")]
+ #[cfg(any(target_os = "haiku", target_os = "illumos", target_os = "solaris"))]
VSWTCH,
- #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
+ #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
+ target_os = "illumos", target_os = "solaris")))]
VTIME,
VWERASE,
#[cfg(target_os = "dragonfly")]
@@ -540,7 +569,8 @@
}
}
-#[cfg(all(target_os = "linux", target_arch = "sparc64"))]
+#[cfg(any(all(target_os = "linux", target_arch = "sparc64"),
+ target_os = "illumos", target_os = "solaris"))]
impl SpecialCharacterIndices {
pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF;
pub const VTIME: SpecialCharacterIndices = SpecialCharacterIndices::VEOL;
@@ -876,7 +906,7 @@
target_os = "netbsd",
target_os = "openbsd"))] {
/// Get input baud rate (see
- /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
+ /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
///
/// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
pub fn cfgetispeed(termios: &Termios) -> u32 {
@@ -885,7 +915,7 @@
}
/// Get output baud rate (see
- /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
+ /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
///
/// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
pub fn cfgetospeed(termios: &Termios) -> u32 {
@@ -894,7 +924,7 @@
}
/// Set input baud rate (see
- /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
+ /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
///
/// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
pub fn cfsetispeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
@@ -905,7 +935,7 @@
}
/// Set output baud rate (see
- /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
+ /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
///
/// `cfsetospeed()` sets the output baud rate in the given termios structure.
pub fn cfsetospeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
@@ -930,7 +960,7 @@
use std::convert::TryInto;
/// Get input baud rate (see
- /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
+ /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
///
/// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
pub fn cfgetispeed(termios: &Termios) -> BaudRate {
@@ -939,7 +969,7 @@
}
/// Get output baud rate (see
- /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
+ /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
///
/// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
pub fn cfgetospeed(termios: &Termios) -> BaudRate {
@@ -948,7 +978,7 @@
}
/// Set input baud rate (see
- /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
+ /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
///
/// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
pub fn cfsetispeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
@@ -959,7 +989,7 @@
}
/// Set output baud rate (see
- /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
+ /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
///
/// `cfsetospeed()` sets the output baud rate in the given `Termios` structure.
pub fn cfsetospeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
@@ -984,7 +1014,7 @@
}
/// Configures the port to something like the "raw" mode of the old Version 7 terminal driver (see
-/// [termios(3)](http://man7.org/linux/man-pages/man3/termios.3.html)).
+/// [termios(3)](https://man7.org/linux/man-pages/man3/termios.3.html)).
///
/// `cfmakeraw()` configures the termios structure such that input is available character-by-
/// character, echoing is disabled, and all special input and output processing is disabled. Note
@@ -1011,7 +1041,7 @@
}
/// Return the configuration of a port
-/// [tcgetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)).
+/// [tcgetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)).
///
/// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying
/// this structure *will not* reconfigure the port, instead the modifications should be done to
@@ -1027,7 +1057,7 @@
}
/// Set the configuration for a terminal (see
-/// [tcsetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)).
+/// [tcsetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)).
///
/// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change
/// takes affect at a time specified by `actions`. Note that this function may return success if
@@ -1038,13 +1068,13 @@
}
/// Block until all output data is written (see
-/// [tcdrain(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
+/// [tcdrain(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
pub fn tcdrain(fd: RawFd) -> Result<()> {
Errno::result(unsafe { libc::tcdrain(fd) }).map(drop)
}
/// Suspend or resume the transmission or reception of data (see
-/// [tcflow(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)).
+/// [tcflow(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)).
///
/// `tcflow()` suspends of resumes the transmission or reception of data for the given port
/// depending on the value of `action`.
@@ -1053,7 +1083,7 @@
}
/// Discard data in the output or input queue (see
-/// [tcflush(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)).
+/// [tcflush(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)).
///
/// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both
/// depending on the value of `action`.
@@ -1062,7 +1092,7 @@
}
/// Send a break for a specific duration (see
-/// [tcsendbreak(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)).
+/// [tcsendbreak(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)).
///
/// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream
/// of zero-valued bits for an implementation-defined duration.
@@ -1071,7 +1101,7 @@
}
/// Get the session controlled by the given terminal (see
-/// [tcgetsid(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
+/// [tcgetsid(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
let res = unsafe { libc::tcgetsid(fd) };
diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs
index 4a24719..e42fffd 100644
--- a/src/sys/timerfd.rs
+++ b/src/sys/timerfd.rs
@@ -3,7 +3,7 @@
//! Timer FD is a Linux-only API to create timers and get expiration
//! notifications through file descriptors.
//!
-//! For more documentation, please read [timerfd_create(2)](http://man7.org/linux/man-pages/man2/timerfd_create.2.html).
+//! For more documentation, please read [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html).
//!
//! # Examples
//!
@@ -56,7 +56,7 @@
libc_enum! {
/// The type of the clock used to mark the progress of the timer. For more
- /// details on each kind of clock, please refer to [timerfd_create(2)](http://man7.org/linux/man-pages/man2/timerfd_create.2.html).
+ /// details on each kind of clock, please refer to [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html).
#[repr(i32)]
pub enum ClockId {
CLOCK_REALTIME,
diff --git a/src/sys/uio.rs b/src/sys/uio.rs
index 6533422..b8ae860 100644
--- a/src/sys/uio.rs
+++ b/src/sys/uio.rs
@@ -112,7 +112,7 @@
///
/// This function is only available on Linux.
///
-/// [`process_vm_writev`(2)]: http://man7.org/linux/man-pages/man2/process_vm_writev.2.html
+/// [`process_vm_writev`(2)]: https://man7.org/linux/man-pages/man2/process_vm_writev.2.html
/// [ptrace]: ../ptrace/index.html
/// [`IoVec`]: struct.IoVec.html
/// [`RemoteIoVec`]: struct.RemoteIoVec.html
@@ -147,7 +147,7 @@
///
/// This function is only available on Linux.
///
-/// [`process_vm_readv`(2)]: http://man7.org/linux/man-pages/man2/process_vm_readv.2.html
+/// [`process_vm_readv`(2)]: https://man7.org/linux/man-pages/man2/process_vm_readv.2.html
/// [`ptrace`]: ../ptrace/index.html
/// [`IoVec`]: struct.IoVec.html
/// [`RemoteIoVec`]: struct.RemoteIoVec.html
diff --git a/src/sys/wait.rs b/src/sys/wait.rs
index faf8543..6c5c0f0 100644
--- a/src/sys/wait.rs
+++ b/src/sys/wait.rs
@@ -81,14 +81,14 @@
/// field is the `PTRACE_EVENT_*` value of the event.
///
/// [`nix::sys::ptrace`]: ../ptrace/index.html
- /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
+ /// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html
#[cfg(any(target_os = "linux", target_os = "android"))]
PtraceEvent(Pid, Signal, c_int),
/// The traced process was stopped by execution of a system call,
/// and `PTRACE_O_TRACESYSGOOD` is in effect. See [`ptrace`(2)] for
/// more information.
///
- /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
+ /// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html
#[cfg(any(target_os = "linux", target_os = "android"))]
PtraceSyscall(Pid),
/// The process was previously stopped but has resumed execution