summaryrefslogtreecommitdiffstats
path: root/vendor/nix/src/sys
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/nix/src/sys')
-rw-r--r--vendor/nix/src/sys/aio.rs1241
-rw-r--r--vendor/nix/src/sys/epoll.rs128
-rw-r--r--vendor/nix/src/sys/event.rs374
-rw-r--r--vendor/nix/src/sys/eventfd.rs17
-rw-r--r--vendor/nix/src/sys/inotify.rs248
-rw-r--r--vendor/nix/src/sys/ioctl/bsd.rs129
-rw-r--r--vendor/nix/src/sys/ioctl/linux.rs172
-rw-r--r--vendor/nix/src/sys/ioctl/mod.rs786
-rw-r--r--vendor/nix/src/sys/memfd.rs64
-rw-r--r--vendor/nix/src/sys/mman.rs599
-rw-r--r--vendor/nix/src/sys/mod.rs228
-rw-r--r--vendor/nix/src/sys/personality.rs93
-rw-r--r--vendor/nix/src/sys/pthread.rs43
-rw-r--r--vendor/nix/src/sys/ptrace/bsd.rs195
-rw-r--r--vendor/nix/src/sys/ptrace/linux.rs558
-rw-r--r--vendor/nix/src/sys/ptrace/mod.rs25
-rw-r--r--vendor/nix/src/sys/quota.rs338
-rw-r--r--vendor/nix/src/sys/reboot.rs48
-rw-r--r--vendor/nix/src/sys/resource.rs443
-rw-r--r--vendor/nix/src/sys/select.rs455
-rw-r--r--vendor/nix/src/sys/sendfile.rs277
-rw-r--r--vendor/nix/src/sys/signal.rs1348
-rw-r--r--vendor/nix/src/sys/signalfd.rs175
-rw-r--r--vendor/nix/src/sys/socket/addr.rs3247
-rw-r--r--vendor/nix/src/sys/socket/mod.rs2487
-rw-r--r--vendor/nix/src/sys/socket/sockopt.rs1422
-rw-r--r--vendor/nix/src/sys/stat.rs480
-rw-r--r--vendor/nix/src/sys/statfs.rs853
-rw-r--r--vendor/nix/src/sys/statvfs.rs173
-rw-r--r--vendor/nix/src/sys/sysinfo.rs83
-rw-r--r--vendor/nix/src/sys/termios.rs1227
-rw-r--r--vendor/nix/src/sys/time.rs811
-rw-r--r--vendor/nix/src/sys/timer.rs187
-rw-r--r--vendor/nix/src/sys/timerfd.rs214
-rw-r--r--vendor/nix/src/sys/uio.rs291
-rw-r--r--vendor/nix/src/sys/utsname.rs85
-rw-r--r--vendor/nix/src/sys/wait.rs388
37 files changed, 0 insertions, 19932 deletions
diff --git a/vendor/nix/src/sys/aio.rs b/vendor/nix/src/sys/aio.rs
deleted file mode 100644
index e2ce19b79..000000000
--- a/vendor/nix/src/sys/aio.rs
+++ /dev/null
@@ -1,1241 +0,0 @@
-// vim: tw=80
-//! POSIX Asynchronous I/O
-//!
-//! The POSIX AIO interface is used for asynchronous I/O on files and disk-like
-//! devices. It supports [`read`](struct.AioRead.html#method.new),
-//! [`write`](struct.AioWrite.html#method.new),
-//! [`fsync`](struct.AioFsync.html#method.new),
-//! [`readv`](struct.AioReadv.html#method.new), and
-//! [`writev`](struct.AioWritev.html#method.new), operations, subject to
-//! platform support. Completion
-//! notifications can optionally be delivered via
-//! [signals](../signal/enum.SigevNotify.html#variant.SigevSignal), via the
-//! [`aio_suspend`](fn.aio_suspend.html) function, or via polling. Some
-//! platforms support other completion
-//! notifications, such as
-//! [kevent](../signal/enum.SigevNotify.html#variant.SigevKevent).
-//!
-//! Multiple operations may be submitted in a batch with
-//! [`lio_listio`](fn.lio_listio.html), though the standard does not guarantee
-//! that they will be executed atomically.
-//!
-//! Outstanding operations may be cancelled with
-//! [`cancel`](trait.Aio.html#method.cancel) or
-//! [`aio_cancel_all`](fn.aio_cancel_all.html), though the operating system may
-//! not support this for all filesystems and devices.
-#[cfg(target_os = "freebsd")]
-use std::io::{IoSlice, IoSliceMut};
-use std::{
- convert::TryFrom,
- fmt::{self, Debug},
- marker::{PhantomData, PhantomPinned},
- mem,
- os::unix::io::RawFd,
- pin::Pin,
- ptr, thread,
-};
-
-use libc::{c_void, off_t};
-use pin_utils::unsafe_pinned;
-
-use crate::{
- errno::Errno,
- sys::{signal::*, time::TimeSpec},
- Result,
-};
-
-libc_enum! {
- /// Mode for `AioCb::fsync`. Controls whether only data or both data and
- /// metadata are synced.
- #[repr(i32)]
- #[non_exhaustive]
- pub enum AioFsyncMode {
- /// do it like `fsync`
- O_SYNC,
- /// on supported operating systems only, do it like `fdatasync`
- #[cfg(any(target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- O_DSYNC
- }
- impl TryFrom<i32>
-}
-
-libc_enum! {
- /// Mode for [`lio_listio`](fn.lio_listio.html)
- #[repr(i32)]
- pub enum LioMode {
- /// Requests that [`lio_listio`](fn.lio_listio.html) block until all
- /// requested operations have been completed
- LIO_WAIT,
- /// Requests that [`lio_listio`](fn.lio_listio.html) return immediately
- LIO_NOWAIT,
- }
-}
-
-/// Return values for [`AioCb::cancel`](struct.AioCb.html#method.cancel) and
-/// [`aio_cancel_all`](fn.aio_cancel_all.html)
-#[repr(i32)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum AioCancelStat {
- /// All outstanding requests were canceled
- AioCanceled = libc::AIO_CANCELED,
- /// Some requests were not canceled. Their status should be checked with
- /// `AioCb::error`
- AioNotCanceled = libc::AIO_NOTCANCELED,
- /// All of the requests have already finished
- AioAllDone = libc::AIO_ALLDONE,
-}
-
-/// Newtype that adds Send and Sync to libc::aiocb, which contains raw pointers
-#[repr(transparent)]
-struct LibcAiocb(libc::aiocb);
-
-unsafe impl Send for LibcAiocb {}
-unsafe impl Sync for LibcAiocb {}
-
-/// Base class for all AIO operations. Should only be used directly when
-/// checking for completion.
-// We could create some kind of AsPinnedMut trait, and implement it for all aio
-// ops, allowing the crate's users to get pinned references to `AioCb`. That
-// could save some code for things like polling methods. But IMHO it would
-// provide polymorphism at the wrong level. Instead, the best place for
-// polymorphism is at the level of `Futures`.
-#[repr(C)]
-struct AioCb {
- aiocb: LibcAiocb,
- /// Could this `AioCb` potentially have any in-kernel state?
- // It would be really nice to perform the in-progress check entirely at
- // compile time. But I can't figure out how, because:
- // * Future::poll takes a `Pin<&mut self>` rather than `self`, and
- // * Rust's lack of an equivalent of C++'s Guaranteed Copy Elision means
- // that there's no way to write an AioCb constructor that neither boxes
- // the object itself, nor moves it during return.
- in_progress: bool,
-}
-
-impl AioCb {
- pin_utils::unsafe_unpinned!(aiocb: LibcAiocb);
-
- fn aio_return(mut self: Pin<&mut Self>) -> Result<usize> {
- self.in_progress = false;
- unsafe {
- let p: *mut libc::aiocb = &mut self.aiocb.0;
- Errno::result(libc::aio_return(p))
- }
- .map(|r| r as usize)
- }
-
- fn cancel(mut self: Pin<&mut Self>) -> Result<AioCancelStat> {
- let r = unsafe {
- libc::aio_cancel(self.aiocb.0.aio_fildes, &mut self.aiocb.0)
- };
- match r {
- libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
- libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
- libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
- -1 => Err(Errno::last()),
- _ => panic!("unknown aio_cancel return value"),
- }
- }
-
- fn common_init(fd: RawFd, prio: i32, sigev_notify: SigevNotify) -> Self {
- // 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
- // explicitly zeroed when allocated.
- let mut a = unsafe { mem::zeroed::<libc::aiocb>() };
- a.aio_fildes = fd;
- a.aio_reqprio = prio;
- a.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
- AioCb {
- aiocb: LibcAiocb(a),
- in_progress: false,
- }
- }
-
- fn error(self: Pin<&mut Self>) -> Result<()> {
- let r = unsafe { libc::aio_error(&self.aiocb().0) };
- match r {
- 0 => Ok(()),
- num if num > 0 => Err(Errno::from_i32(num)),
- -1 => Err(Errno::last()),
- num => panic!("unknown aio_error return value {:?}", num),
- }
- }
-
- fn in_progress(&self) -> bool {
- self.in_progress
- }
-
- fn set_in_progress(mut self: Pin<&mut Self>) {
- self.as_mut().in_progress = true;
- }
-
- /// Update the notification settings for an existing AIO operation that has
- /// not yet been submitted.
- // Takes a normal reference rather than a pinned one because this method is
- // normally called before the object needs to be pinned, that is, before
- // it's been submitted to the kernel.
- fn set_sigev_notify(&mut self, sigev_notify: SigevNotify) {
- assert!(
- !self.in_progress,
- "Can't change notification settings for an in-progress operation"
- );
- self.aiocb.0.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
- }
-}
-
-impl Debug for AioCb {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- fmt.debug_struct("AioCb")
- .field("aiocb", &self.aiocb.0)
- .field("in_progress", &self.in_progress)
- .finish()
- }
-}
-
-impl Drop for AioCb {
- /// If the `AioCb` has no remaining state in the kernel, just drop it.
- /// Otherwise, dropping constitutes a resource leak, which is an error
- fn drop(&mut self) {
- assert!(
- thread::panicking() || !self.in_progress,
- "Dropped an in-progress AioCb"
- );
- }
-}
-
-/// Methods common to all AIO operations
-pub trait Aio {
- /// The return type of [`Aio::aio_return`].
- type Output;
-
- /// Retrieve return status of an asynchronous operation.
- ///
- /// Should only be called once for each operation, after [`Aio::error`]
- /// indicates that it has completed. The result is the same as for the
- /// synchronous `read(2)`, `write(2)`, of `fsync(2)` functions.
- ///
- /// # References
- ///
- /// [aio_return](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html)
- fn aio_return(self: Pin<&mut Self>) -> Result<Self::Output>;
-
- /// Cancels an outstanding AIO request.
- ///
- /// The operating system is not required to implement cancellation for all
- /// file and device types. Even if it does, there is no guarantee that the
- /// operation has not already completed. So the caller must check the
- /// result and handle operations that were not canceled or that have already
- /// completed.
- ///
- /// # Examples
- ///
- /// Cancel an outstanding aio operation. Note that we must still call
- /// `aio_return` to free resources, even though we don't care about the
- /// result.
- ///
- /// ```
- /// # 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;
- /// let wbuf = b"CDEF";
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = Box::pin(AioWrite::new(f.as_raw_fd(),
- /// 2, //offset
- /// &wbuf[..],
- /// 0, //priority
- /// SigevNotify::SigevNone));
- /// aiocb.as_mut().submit().unwrap();
- /// let cs = aiocb.as_mut().cancel().unwrap();
- /// if cs == AioCancelStat::AioNotCanceled {
- /// while (aiocb.as_mut().error() == Err(Errno::EINPROGRESS)) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// }
- /// // Must call `aio_return`, but ignore the result
- /// let _ = aiocb.as_mut().aio_return();
- /// ```
- ///
- /// # References
- ///
- /// [aio_cancel](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
- fn cancel(self: Pin<&mut Self>) -> Result<AioCancelStat>;
-
- /// Retrieve error status of an asynchronous operation.
- ///
- /// If the request has not yet completed, returns `EINPROGRESS`. Otherwise,
- /// returns `Ok` or any other error.
- ///
- /// # Examples
- ///
- /// Issue an aio operation and use `error` to poll for completion. Polling
- /// is an alternative to `aio_suspend`, used by most of the other examples.
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::{thread, time};
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// const WBUF: &[u8] = b"abcdef123456";
- /// let mut f = tempfile().unwrap();
- /// let mut aiocb = Box::pin(AioWrite::new(f.as_raw_fd(),
- /// 2, //offset
- /// WBUF,
- /// 0, //priority
- /// SigevNotify::SigevNone));
- /// aiocb.as_mut().submit().unwrap();
- /// while (aiocb.as_mut().error() == Err(Errno::EINPROGRESS)) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// assert_eq!(aiocb.as_mut().aio_return().unwrap(), WBUF.len());
- /// ```
- ///
- /// # References
- ///
- /// [aio_error](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_error.html)
- fn error(self: Pin<&mut Self>) -> Result<()>;
-
- /// Returns the underlying file descriptor associated with the operation.
- fn fd(&self) -> RawFd;
-
- /// Does this operation currently have any in-kernel state?
- ///
- /// Dropping an operation that does have in-kernel state constitutes a
- /// resource leak.
- ///
- /// # Examples
- ///
- /// ```
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify::SigevNone;
- /// # use std::{thread, time};
- /// # use std::os::unix::io::AsRawFd;
- /// # use tempfile::tempfile;
- /// let f = tempfile().unwrap();
- /// let mut aiof = Box::pin(AioFsync::new(f.as_raw_fd(), AioFsyncMode::O_SYNC,
- /// 0, SigevNone));
- /// assert!(!aiof.as_mut().in_progress());
- /// aiof.as_mut().submit().expect("aio_fsync failed early");
- /// assert!(aiof.as_mut().in_progress());
- /// while (aiof.as_mut().error() == Err(Errno::EINPROGRESS)) {
- /// thread::sleep(time::Duration::from_millis(10));
- /// }
- /// aiof.as_mut().aio_return().expect("aio_fsync failed late");
- /// assert!(!aiof.as_mut().in_progress());
- /// ```
- fn in_progress(&self) -> bool;
-
- /// Returns the priority of the `AioCb`
- fn priority(&self) -> i32;
-
- /// Update the notification settings for an existing AIO operation that has
- /// not yet been submitted.
- fn set_sigev_notify(&mut self, sev: SigevNotify);
-
- /// Returns the `SigEvent` that will be used for notification.
- fn sigevent(&self) -> SigEvent;
-
- /// Actually start the I/O operation.
- ///
- /// After calling this method and until [`Aio::aio_return`] returns `Ok`,
- /// the structure may not be moved in memory.
- fn submit(self: Pin<&mut Self>) -> Result<()>;
-}
-
-macro_rules! aio_methods {
- () => {
- fn cancel(self: Pin<&mut Self>) -> Result<AioCancelStat> {
- self.aiocb().cancel()
- }
-
- fn error(self: Pin<&mut Self>) -> Result<()> {
- self.aiocb().error()
- }
-
- fn fd(&self) -> RawFd {
- self.aiocb.aiocb.0.aio_fildes
- }
-
- fn in_progress(&self) -> bool {
- self.aiocb.in_progress()
- }
-
- fn priority(&self) -> i32 {
- self.aiocb.aiocb.0.aio_reqprio
- }
-
- fn set_sigev_notify(&mut self, sev: SigevNotify) {
- self.aiocb.set_sigev_notify(sev)
- }
-
- fn sigevent(&self) -> SigEvent {
- SigEvent::from(&self.aiocb.aiocb.0.aio_sigevent)
- }
- };
- ($func:ident) => {
- aio_methods!();
-
- fn aio_return(self: Pin<&mut Self>) -> Result<<Self as Aio>::Output> {
- self.aiocb().aio_return()
- }
-
- fn submit(mut self: Pin<&mut Self>) -> Result<()> {
- let p: *mut libc::aiocb = &mut self.as_mut().aiocb().aiocb.0;
- Errno::result({ unsafe { libc::$func(p) } }).map(|_| {
- self.aiocb().set_in_progress();
- })
- }
- };
-}
-
-/// An asynchronous version of `fsync(2)`.
-///
-/// # References
-///
-/// [aio_fsync](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_fsync.html)
-/// # Examples
-///
-/// ```
-/// # use nix::errno::Errno;
-/// # use nix::Error;
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::SigevNotify::SigevNone;
-/// # use std::{thread, time};
-/// # use std::os::unix::io::AsRawFd;
-/// # use tempfile::tempfile;
-/// let f = tempfile().unwrap();
-/// let mut aiof = Box::pin(AioFsync::new(f.as_raw_fd(), AioFsyncMode::O_SYNC,
-/// 0, SigevNone));
-/// aiof.as_mut().submit().expect("aio_fsync failed early");
-/// while (aiof.as_mut().error() == Err(Errno::EINPROGRESS)) {
-/// thread::sleep(time::Duration::from_millis(10));
-/// }
-/// aiof.as_mut().aio_return().expect("aio_fsync failed late");
-/// ```
-#[derive(Debug)]
-#[repr(transparent)]
-pub struct AioFsync {
- aiocb: AioCb,
- _pin: PhantomPinned,
-}
-
-impl AioFsync {
- unsafe_pinned!(aiocb: AioCb);
-
- /// Returns the operation's fsync mode: data and metadata or data only?
- pub fn mode(&self) -> AioFsyncMode {
- AioFsyncMode::try_from(self.aiocb.aiocb.0.aio_lio_opcode).unwrap()
- }
-
- /// Create a new `AioFsync`.
- ///
- /// # Arguments
- ///
- /// * `fd`: File descriptor to sync.
- /// * `mode`: Whether to sync file metadata too, or just data.
- /// * `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.
- pub fn new(
- fd: RawFd,
- mode: AioFsyncMode,
- prio: i32,
- sigev_notify: SigevNotify,
- ) -> Self {
- let mut aiocb = AioCb::common_init(fd, prio, sigev_notify);
- // To save some memory, store mode in an unused field of the AioCb.
- // True it isn't very much memory, but downstream creates will likely
- // create an enum containing this and other AioCb variants and pack
- // those enums into data structures like Vec, so it adds up.
- aiocb.aiocb.0.aio_lio_opcode = mode as libc::c_int;
- AioFsync {
- aiocb,
- _pin: PhantomPinned,
- }
- }
-}
-
-impl Aio for AioFsync {
- type Output = ();
-
- aio_methods!();
-
- fn aio_return(self: Pin<&mut Self>) -> Result<()> {
- self.aiocb().aio_return().map(drop)
- }
-
- fn submit(mut self: Pin<&mut Self>) -> Result<()> {
- let aiocb = &mut self.as_mut().aiocb().aiocb.0;
- let mode = mem::replace(&mut aiocb.aio_lio_opcode, 0);
- let p: *mut libc::aiocb = aiocb;
- Errno::result(unsafe { libc::aio_fsync(mode, p) }).map(|_| {
- self.aiocb().set_in_progress();
- })
- }
-}
-
-// AioFsync does not need AsMut, since it can't be used with lio_listio
-
-impl AsRef<libc::aiocb> for AioFsync {
- fn as_ref(&self) -> &libc::aiocb {
- &self.aiocb.aiocb.0
- }
-}
-
-/// Asynchronously reads from a file descriptor into a buffer
-///
-/// # References
-///
-/// [aio_read](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_read.html)
-///
-/// # Examples
-///
-///
-/// ```
-/// # 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;
-/// const INITIAL: &[u8] = b"abcdef123456";
-/// const LEN: usize = 4;
-/// let mut rbuf = vec![0; LEN];
-/// let mut f = tempfile().unwrap();
-/// f.write_all(INITIAL).unwrap();
-/// {
-/// let mut aior = Box::pin(
-/// AioRead::new(
-/// f.as_raw_fd(),
-/// 2, //offset
-/// &mut rbuf,
-/// 0, //priority
-/// SigevNotify::SigevNone
-/// )
-/// );
-/// aior.as_mut().submit().unwrap();
-/// while (aior.as_mut().error() == Err(Errno::EINPROGRESS)) {
-/// thread::sleep(time::Duration::from_millis(10));
-/// }
-/// assert_eq!(aior.as_mut().aio_return().unwrap(), LEN);
-/// }
-/// assert_eq!(rbuf, b"cdef");
-/// ```
-#[derive(Debug)]
-#[repr(transparent)]
-pub struct AioRead<'a> {
- aiocb: AioCb,
- _data: PhantomData<&'a [u8]>,
- _pin: PhantomPinned,
-}
-
-impl<'a> AioRead<'a> {
- unsafe_pinned!(aiocb: AioCb);
-
- /// Returns the requested length of the aio operation in bytes
- ///
- /// This method returns the *requested* length of the operation. To get the
- /// number of bytes actually read or written by a completed operation, use
- /// `aio_return` instead.
- pub fn nbytes(&self) -> usize {
- self.aiocb.aiocb.0.aio_nbytes
- }
-
- /// Create a new `AioRead`, placing the data in a mutable slice.
- ///
- /// # Arguments
- ///
- /// * `fd`: File descriptor to read from
- /// * `offs`: File offset
- /// * `buf`: A memory buffer. It must outlive the `AioRead`.
- /// * `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.
- pub fn new(
- fd: RawFd,
- offs: off_t,
- buf: &'a mut [u8],
- prio: i32,
- sigev_notify: SigevNotify,
- ) -> Self {
- let mut aiocb = AioCb::common_init(fd, prio, sigev_notify);
- aiocb.aiocb.0.aio_nbytes = buf.len();
- aiocb.aiocb.0.aio_buf = buf.as_mut_ptr() as *mut c_void;
- aiocb.aiocb.0.aio_lio_opcode = libc::LIO_READ;
- aiocb.aiocb.0.aio_offset = offs;
- AioRead {
- aiocb,
- _data: PhantomData,
- _pin: PhantomPinned,
- }
- }
-
- /// Returns the file offset of the operation.
- pub fn offset(&self) -> off_t {
- self.aiocb.aiocb.0.aio_offset
- }
-}
-
-impl<'a> Aio for AioRead<'a> {
- type Output = usize;
-
- aio_methods!(aio_read);
-}
-
-impl<'a> AsMut<libc::aiocb> for AioRead<'a> {
- fn as_mut(&mut self) -> &mut libc::aiocb {
- &mut self.aiocb.aiocb.0
- }
-}
-
-impl<'a> AsRef<libc::aiocb> for AioRead<'a> {
- fn as_ref(&self) -> &libc::aiocb {
- &self.aiocb.aiocb.0
- }
-}
-
-/// Asynchronously reads from a file descriptor into a scatter/gather list of buffers.
-///
-/// # References
-///
-/// [aio_readv](https://www.freebsd.org/cgi/man.cgi?query=aio_readv)
-///
-/// # Examples
-///
-///
-#[cfg_attr(fbsd14, doc = " ```")]
-#[cfg_attr(not(fbsd14), doc = " ```no_run")]
-/// # use nix::errno::Errno;
-/// # use nix::Error;
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::SigevNotify;
-/// # use std::{thread, time};
-/// # use std::io::{IoSliceMut, Write};
-/// # use std::os::unix::io::AsRawFd;
-/// # use tempfile::tempfile;
-/// const INITIAL: &[u8] = b"abcdef123456";
-/// let mut rbuf0 = vec![0; 4];
-/// let mut rbuf1 = vec![0; 2];
-/// let expected_len = rbuf0.len() + rbuf1.len();
-/// let mut rbufs = [IoSliceMut::new(&mut rbuf0), IoSliceMut::new(&mut rbuf1)];
-/// let mut f = tempfile().unwrap();
-/// f.write_all(INITIAL).unwrap();
-/// {
-/// let mut aior = Box::pin(
-/// AioReadv::new(
-/// f.as_raw_fd(),
-/// 2, //offset
-/// &mut rbufs,
-/// 0, //priority
-/// SigevNotify::SigevNone
-/// )
-/// );
-/// aior.as_mut().submit().unwrap();
-/// while (aior.as_mut().error() == Err(Errno::EINPROGRESS)) {
-/// thread::sleep(time::Duration::from_millis(10));
-/// }
-/// assert_eq!(aior.as_mut().aio_return().unwrap(), expected_len);
-/// }
-/// assert_eq!(rbuf0, b"cdef");
-/// assert_eq!(rbuf1, b"12");
-/// ```
-#[cfg(target_os = "freebsd")]
-#[derive(Debug)]
-#[repr(transparent)]
-pub struct AioReadv<'a> {
- aiocb: AioCb,
- _data: PhantomData<&'a [&'a [u8]]>,
- _pin: PhantomPinned,
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> AioReadv<'a> {
- unsafe_pinned!(aiocb: AioCb);
-
- /// Returns the number of buffers the operation will read into.
- pub fn iovlen(&self) -> usize {
- self.aiocb.aiocb.0.aio_nbytes
- }
-
- /// Create a new `AioReadv`, placing the data in a list of mutable slices.
- ///
- /// # Arguments
- ///
- /// * `fd`: File descriptor to read from
- /// * `offs`: File offset
- /// * `bufs`: A scatter/gather list of memory buffers. They must
- /// outlive the `AioReadv`.
- /// * `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.
- pub fn new(
- fd: RawFd,
- offs: off_t,
- bufs: &mut [IoSliceMut<'a>],
- prio: i32,
- sigev_notify: SigevNotify,
- ) -> Self {
- let mut aiocb = AioCb::common_init(fd, prio, sigev_notify);
- // In vectored mode, aio_nbytes stores the length of the iovec array,
- // not the byte count.
- aiocb.aiocb.0.aio_nbytes = bufs.len();
- aiocb.aiocb.0.aio_buf = bufs.as_mut_ptr() as *mut c_void;
- aiocb.aiocb.0.aio_lio_opcode = libc::LIO_READV;
- aiocb.aiocb.0.aio_offset = offs;
- AioReadv {
- aiocb,
- _data: PhantomData,
- _pin: PhantomPinned,
- }
- }
-
- /// Returns the file offset of the operation.
- pub fn offset(&self) -> off_t {
- self.aiocb.aiocb.0.aio_offset
- }
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> Aio for AioReadv<'a> {
- type Output = usize;
-
- aio_methods!(aio_readv);
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> AsMut<libc::aiocb> for AioReadv<'a> {
- fn as_mut(&mut self) -> &mut libc::aiocb {
- &mut self.aiocb.aiocb.0
- }
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> AsRef<libc::aiocb> for AioReadv<'a> {
- fn as_ref(&self) -> &libc::aiocb {
- &self.aiocb.aiocb.0
- }
-}
-
-/// Asynchronously writes from a buffer to a file descriptor
-///
-/// # References
-///
-/// [aio_write](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_write.html)
-///
-/// # Examples
-///
-/// ```
-/// # use nix::errno::Errno;
-/// # use nix::Error;
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::SigevNotify;
-/// # use std::{thread, time};
-/// # use std::os::unix::io::AsRawFd;
-/// # use tempfile::tempfile;
-/// const WBUF: &[u8] = b"abcdef123456";
-/// let mut f = tempfile().unwrap();
-/// let mut aiow = Box::pin(
-/// AioWrite::new(
-/// f.as_raw_fd(),
-/// 2, //offset
-/// WBUF,
-/// 0, //priority
-/// SigevNotify::SigevNone
-/// )
-/// );
-/// aiow.as_mut().submit().unwrap();
-/// while (aiow.as_mut().error() == Err(Errno::EINPROGRESS)) {
-/// thread::sleep(time::Duration::from_millis(10));
-/// }
-/// assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());
-/// ```
-#[derive(Debug)]
-#[repr(transparent)]
-pub struct AioWrite<'a> {
- aiocb: AioCb,
- _data: PhantomData<&'a [u8]>,
- _pin: PhantomPinned,
-}
-
-impl<'a> AioWrite<'a> {
- unsafe_pinned!(aiocb: AioCb);
-
- /// Returns the requested length of the aio operation in bytes
- ///
- /// This method returns the *requested* length of the operation. To get the
- /// number of bytes actually read or written by a completed operation, use
- /// `aio_return` instead.
- pub fn nbytes(&self) -> usize {
- self.aiocb.aiocb.0.aio_nbytes
- }
-
- /// Construct a new `AioWrite`.
- ///
- /// # Arguments
- ///
- /// * `fd`: File descriptor to write to
- /// * `offs`: File offset
- /// * `buf`: A memory buffer. It must outlive the `AioWrite`.
- /// * `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.
- pub fn new(
- fd: RawFd,
- offs: off_t,
- buf: &'a [u8],
- prio: i32,
- sigev_notify: SigevNotify,
- ) -> Self {
- let mut aiocb = AioCb::common_init(fd, prio, sigev_notify);
- aiocb.aiocb.0.aio_nbytes = buf.len();
- // casting an immutable buffer to a mutable pointer looks unsafe,
- // but technically its only unsafe to dereference it, not to create
- // it. Type Safety guarantees that we'll never pass aiocb to
- // aio_read or aio_readv.
- aiocb.aiocb.0.aio_buf = buf.as_ptr() as *mut c_void;
- aiocb.aiocb.0.aio_lio_opcode = libc::LIO_WRITE;
- aiocb.aiocb.0.aio_offset = offs;
- AioWrite {
- aiocb,
- _data: PhantomData,
- _pin: PhantomPinned,
- }
- }
-
- /// Returns the file offset of the operation.
- pub fn offset(&self) -> off_t {
- self.aiocb.aiocb.0.aio_offset
- }
-}
-
-impl<'a> Aio for AioWrite<'a> {
- type Output = usize;
-
- aio_methods!(aio_write);
-}
-
-impl<'a> AsMut<libc::aiocb> for AioWrite<'a> {
- fn as_mut(&mut self) -> &mut libc::aiocb {
- &mut self.aiocb.aiocb.0
- }
-}
-
-impl<'a> AsRef<libc::aiocb> for AioWrite<'a> {
- fn as_ref(&self) -> &libc::aiocb {
- &self.aiocb.aiocb.0
- }
-}
-
-/// Asynchronously writes from a scatter/gather list of buffers to a file descriptor.
-///
-/// # References
-///
-/// [aio_writev](https://www.freebsd.org/cgi/man.cgi?query=aio_writev)
-///
-/// # Examples
-///
-#[cfg_attr(fbsd14, doc = " ```")]
-#[cfg_attr(not(fbsd14), doc = " ```no_run")]
-/// # use nix::errno::Errno;
-/// # use nix::Error;
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::SigevNotify;
-/// # use std::{thread, time};
-/// # use std::io::IoSlice;
-/// # use std::os::unix::io::AsRawFd;
-/// # use tempfile::tempfile;
-/// const wbuf0: &[u8] = b"abcdef";
-/// const wbuf1: &[u8] = b"123456";
-/// let len = wbuf0.len() + wbuf1.len();
-/// let wbufs = [IoSlice::new(wbuf0), IoSlice::new(wbuf1)];
-/// let mut f = tempfile().unwrap();
-/// let mut aiow = Box::pin(
-/// AioWritev::new(
-/// f.as_raw_fd(),
-/// 2, //offset
-/// &wbufs,
-/// 0, //priority
-/// SigevNotify::SigevNone
-/// )
-/// );
-/// aiow.as_mut().submit().unwrap();
-/// while (aiow.as_mut().error() == Err(Errno::EINPROGRESS)) {
-/// thread::sleep(time::Duration::from_millis(10));
-/// }
-/// assert_eq!(aiow.as_mut().aio_return().unwrap(), len);
-/// ```
-#[cfg(target_os = "freebsd")]
-#[derive(Debug)]
-#[repr(transparent)]
-pub struct AioWritev<'a> {
- aiocb: AioCb,
- _data: PhantomData<&'a [&'a [u8]]>,
- _pin: PhantomPinned,
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> AioWritev<'a> {
- unsafe_pinned!(aiocb: AioCb);
-
- /// Returns the number of buffers the operation will read into.
- pub fn iovlen(&self) -> usize {
- self.aiocb.aiocb.0.aio_nbytes
- }
-
- /// Construct a new `AioWritev`.
- ///
- /// # Arguments
- ///
- /// * `fd`: File descriptor to write to
- /// * `offs`: File offset
- /// * `bufs`: A scatter/gather list of memory buffers. They must
- /// outlive the `AioWritev`.
- /// * `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.
- pub fn new(
- fd: RawFd,
- offs: off_t,
- bufs: &[IoSlice<'a>],
- prio: i32,
- sigev_notify: SigevNotify,
- ) -> Self {
- let mut aiocb = AioCb::common_init(fd, prio, sigev_notify);
- // In vectored mode, aio_nbytes stores the length of the iovec array,
- // not the byte count.
- aiocb.aiocb.0.aio_nbytes = bufs.len();
- // casting an immutable buffer to a mutable pointer looks unsafe,
- // but technically its only unsafe to dereference it, not to create
- // it. Type Safety guarantees that we'll never pass aiocb to
- // aio_read or aio_readv.
- aiocb.aiocb.0.aio_buf = bufs.as_ptr() as *mut c_void;
- aiocb.aiocb.0.aio_lio_opcode = libc::LIO_WRITEV;
- aiocb.aiocb.0.aio_offset = offs;
- AioWritev {
- aiocb,
- _data: PhantomData,
- _pin: PhantomPinned,
- }
- }
-
- /// Returns the file offset of the operation.
- pub fn offset(&self) -> off_t {
- self.aiocb.aiocb.0.aio_offset
- }
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> Aio for AioWritev<'a> {
- type Output = usize;
-
- aio_methods!(aio_writev);
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> AsMut<libc::aiocb> for AioWritev<'a> {
- fn as_mut(&mut self) -> &mut libc::aiocb {
- &mut self.aiocb.aiocb.0
- }
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> AsRef<libc::aiocb> for AioWritev<'a> {
- fn as_ref(&self) -> &libc::aiocb {
- &self.aiocb.aiocb.0
- }
-}
-
-/// Cancels outstanding AIO requests for a given file descriptor.
-///
-/// # Examples
-///
-/// Issue an aio operation, then cancel all outstanding operations on that file
-/// descriptor.
-///
-/// ```
-/// # 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;
-/// let wbuf = b"CDEF";
-/// let mut f = tempfile().unwrap();
-/// let mut aiocb = Box::pin(AioWrite::new(f.as_raw_fd(),
-/// 2, //offset
-/// &wbuf[..],
-/// 0, //priority
-/// SigevNotify::SigevNone));
-/// aiocb.as_mut().submit().unwrap();
-/// let cs = aio_cancel_all(f.as_raw_fd()).unwrap();
-/// if cs == AioCancelStat::AioNotCanceled {
-/// while (aiocb.as_mut().error() == Err(Errno::EINPROGRESS)) {
-/// thread::sleep(time::Duration::from_millis(10));
-/// }
-/// }
-/// // Must call `aio_return`, but ignore the result
-/// let _ = aiocb.as_mut().aio_return();
-/// ```
-///
-/// # References
-///
-/// [`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, ptr::null_mut()) } {
- libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
- libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
- libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
- -1 => Err(Errno::last()),
- _ => panic!("unknown aio_cancel return value"),
- }
-}
-
-/// Suspends the calling process until at least one of the specified operations
-/// have completed, a signal is delivered, or the timeout has passed.
-///
-/// If `timeout` is `None`, `aio_suspend` will block indefinitely.
-///
-/// # Examples
-///
-/// Use `aio_suspend` to block until an aio operation completes.
-///
-/// ```
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::SigevNotify;
-/// # use std::os::unix::io::AsRawFd;
-/// # use tempfile::tempfile;
-/// const WBUF: &[u8] = b"abcdef123456";
-/// let mut f = tempfile().unwrap();
-/// let mut aiocb = Box::pin(AioWrite::new(f.as_raw_fd(),
-/// 2, //offset
-/// WBUF,
-/// 0, //priority
-/// SigevNotify::SigevNone));
-/// aiocb.as_mut().submit().unwrap();
-/// aio_suspend(&[&*aiocb], None).expect("aio_suspend failed");
-/// assert_eq!(aiocb.as_mut().aio_return().unwrap() as usize, WBUF.len());
-/// ```
-/// # References
-///
-/// [`aio_suspend`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_suspend.html)
-pub fn aio_suspend(
- list: &[&dyn AsRef<libc::aiocb>],
- timeout: Option<TimeSpec>,
-) -> Result<()> {
- let p = list as *const [&dyn AsRef<libc::aiocb>]
- as *const [*const libc::aiocb] as *const *const libc::aiocb;
- let timep = match timeout {
- None => ptr::null::<libc::timespec>(),
- Some(x) => x.as_ref() as *const libc::timespec,
- };
- Errno::result(unsafe { libc::aio_suspend(p, list.len() as i32, timep) })
- .map(drop)
-}
-
-/// Submits multiple asynchronous I/O requests with a single system call.
-///
-/// They are not guaranteed to complete atomically, and the order in which the
-/// requests are carried out is not specified. Reads, and writes may be freely
-/// mixed.
-///
-/// # Examples
-///
-/// Use `lio_listio` to submit an aio operation and wait for its completion. In
-/// this case, there is no need to use aio_suspend to wait or `error` to poll.
-/// This mode is useful for otherwise-synchronous programs that want to execute
-/// a handful of I/O operations in parallel.
-/// ```
-/// # use std::os::unix::io::AsRawFd;
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::SigevNotify;
-/// # use tempfile::tempfile;
-/// const WBUF: &[u8] = b"abcdef123456";
-/// let mut f = tempfile().unwrap();
-/// let mut aiow = Box::pin(AioWrite::new(
-/// f.as_raw_fd(),
-/// 2, // offset
-/// WBUF,
-/// 0, // priority
-/// SigevNotify::SigevNone
-/// ));
-/// lio_listio(LioMode::LIO_WAIT, &mut[aiow.as_mut()], SigevNotify::SigevNone)
-/// .unwrap();
-/// // At this point, we are guaranteed that aiow is complete.
-/// assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());
-/// ```
-///
-/// Use `lio_listio` to submit multiple asynchronous operations with a single
-/// syscall, but receive notification individually. This is an efficient
-/// technique for reducing overall context-switch overhead, especially when
-/// combined with kqueue.
-/// ```
-/// # use std::os::unix::io::AsRawFd;
-/// # use std::thread;
-/// # use std::time;
-/// # use nix::errno::Errno;
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::SigevNotify;
-/// # use tempfile::tempfile;
-/// const WBUF: &[u8] = b"abcdef123456";
-/// let mut f = tempfile().unwrap();
-/// let mut aiow = Box::pin(AioWrite::new(
-/// f.as_raw_fd(),
-/// 2, // offset
-/// WBUF,
-/// 0, // priority
-/// SigevNotify::SigevNone
-/// ));
-/// lio_listio(LioMode::LIO_NOWAIT, &mut[aiow.as_mut()], SigevNotify::SigevNone)
-/// .unwrap();
-/// // We must wait for the completion of each individual operation
-/// while (aiow.as_mut().error() == Err(Errno::EINPROGRESS)) {
-/// thread::sleep(time::Duration::from_millis(10));
-/// }
-/// assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());
-/// ```
-///
-/// Use `lio_listio` to submit multiple operations, and receive notification
-/// only when all of them are complete. This can be useful when there is some
-/// logical relationship between the operations. But beware! Errors or system
-/// resource limitations may cause `lio_listio` to return `EIO`, `EAGAIN`, or
-/// `EINTR`, in which case some but not all operations may have been submitted.
-/// In that case, you must check the status of each individual operation, and
-/// possibly resubmit some.
-/// ```
-/// # use libc::c_int;
-/// # use std::os::unix::io::AsRawFd;
-/// # use std::sync::atomic::{AtomicBool, Ordering};
-/// # use std::thread;
-/// # use std::time;
-/// # use lazy_static::lazy_static;
-/// # use nix::errno::Errno;
-/// # use nix::sys::aio::*;
-/// # use nix::sys::signal::*;
-/// # use tempfile::tempfile;
-/// lazy_static! {
-/// pub static ref SIGNALED: AtomicBool = AtomicBool::new(false);
-/// }
-///
-/// extern fn sigfunc(_: c_int) {
-/// SIGNALED.store(true, Ordering::Relaxed);
-/// }
-/// let sa = SigAction::new(SigHandler::Handler(sigfunc),
-/// SaFlags::SA_RESETHAND,
-/// SigSet::empty());
-/// SIGNALED.store(false, Ordering::Relaxed);
-/// unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
-///
-/// const WBUF: &[u8] = b"abcdef123456";
-/// let mut f = tempfile().unwrap();
-/// let mut aiow = Box::pin(AioWrite::new(
-/// f.as_raw_fd(),
-/// 2, // offset
-/// WBUF,
-/// 0, // priority
-/// SigevNotify::SigevNone
-/// ));
-/// let sev = SigevNotify::SigevSignal { signal: Signal::SIGUSR2, si_value: 0 };
-/// lio_listio(LioMode::LIO_NOWAIT, &mut[aiow.as_mut()], sev).unwrap();
-/// while !SIGNALED.load(Ordering::Relaxed) {
-/// thread::sleep(time::Duration::from_millis(10));
-/// }
-/// // At this point, since `lio_listio` returned success and delivered its
-/// // notification, we know that all operations are complete.
-/// assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());
-/// ```
-pub fn lio_listio(
- mode: LioMode,
- list: &mut [Pin<&mut dyn AsMut<libc::aiocb>>],
- sigev_notify: SigevNotify,
-) -> Result<()> {
- let p = list as *mut [Pin<&mut dyn AsMut<libc::aiocb>>]
- as *mut [*mut libc::aiocb] as *mut *mut libc::aiocb;
- let sigev = SigEvent::new(sigev_notify);
- let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
- Errno::result(unsafe {
- libc::lio_listio(mode as i32, p, list.len() as i32, sigevp)
- })
- .map(drop)
-}
-
-#[cfg(test)]
-mod t {
- use super::*;
-
- /// aio_suspend relies on casting Rust Aio* struct pointers to libc::aiocb
- /// pointers. This test ensures that such casts are valid.
- #[test]
- fn casting() {
- let sev = SigevNotify::SigevNone;
- let aiof = AioFsync::new(666, AioFsyncMode::O_SYNC, 0, sev);
- assert_eq!(
- aiof.as_ref() as *const libc::aiocb,
- &aiof as *const AioFsync as *const libc::aiocb
- );
-
- let mut rbuf = [];
- let aior = AioRead::new(666, 0, &mut rbuf, 0, sev);
- assert_eq!(
- aior.as_ref() as *const libc::aiocb,
- &aior as *const AioRead as *const libc::aiocb
- );
-
- let wbuf = [];
- let aiow = AioWrite::new(666, 0, &wbuf, 0, sev);
- assert_eq!(
- aiow.as_ref() as *const libc::aiocb,
- &aiow as *const AioWrite as *const libc::aiocb
- );
- }
-
- #[cfg(target_os = "freebsd")]
- #[test]
- fn casting_vectored() {
- let sev = SigevNotify::SigevNone;
-
- let mut rbuf = [];
- let mut rbufs = [IoSliceMut::new(&mut rbuf)];
- let aiorv = AioReadv::new(666, 0, &mut rbufs[..], 0, sev);
- assert_eq!(
- aiorv.as_ref() as *const libc::aiocb,
- &aiorv as *const AioReadv as *const libc::aiocb
- );
-
- let wbuf = [];
- let wbufs = [IoSlice::new(&wbuf)];
- let aiowv = AioWritev::new(666, 0, &wbufs, 0, sev);
- assert_eq!(
- aiowv.as_ref() as *const libc::aiocb,
- &aiowv as *const AioWritev as *const libc::aiocb
- );
- }
-}
diff --git a/vendor/nix/src/sys/epoll.rs b/vendor/nix/src/sys/epoll.rs
deleted file mode 100644
index 58def2e78..000000000
--- a/vendor/nix/src/sys/epoll.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-use crate::errno::Errno;
-use crate::Result;
-use libc::{self, c_int};
-use std::mem;
-use std::os::unix::io::RawFd;
-use std::ptr;
-
-libc_bitflags!(
- pub struct EpollFlags: c_int {
- EPOLLIN;
- EPOLLPRI;
- EPOLLOUT;
- EPOLLRDNORM;
- EPOLLRDBAND;
- EPOLLWRNORM;
- EPOLLWRBAND;
- EPOLLMSG;
- EPOLLERR;
- EPOLLHUP;
- EPOLLRDHUP;
- EPOLLEXCLUSIVE;
- #[cfg(not(target_arch = "mips"))]
- EPOLLWAKEUP;
- EPOLLONESHOT;
- EPOLLET;
- }
-);
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(i32)]
-#[non_exhaustive]
-pub enum EpollOp {
- EpollCtlAdd = libc::EPOLL_CTL_ADD,
- EpollCtlDel = libc::EPOLL_CTL_DEL,
- EpollCtlMod = libc::EPOLL_CTL_MOD,
-}
-
-libc_bitflags! {
- pub struct EpollCreateFlags: c_int {
- EPOLL_CLOEXEC;
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(transparent)]
-pub struct EpollEvent {
- event: libc::epoll_event,
-}
-
-impl EpollEvent {
- pub fn new(events: EpollFlags, data: u64) -> Self {
- EpollEvent {
- event: libc::epoll_event {
- events: events.bits() as u32,
- u64: data,
- },
- }
- }
-
- pub fn empty() -> Self {
- unsafe { mem::zeroed::<EpollEvent>() }
- }
-
- pub fn events(&self) -> EpollFlags {
- EpollFlags::from_bits(self.event.events as c_int).unwrap()
- }
-
- pub fn data(&self) -> u64 {
- self.event.u64
- }
-}
-
-#[inline]
-pub fn epoll_create() -> Result<RawFd> {
- let res = unsafe { libc::epoll_create(1024) };
-
- Errno::result(res)
-}
-
-#[inline]
-pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
- let res = unsafe { libc::epoll_create1(flags.bits()) };
-
- Errno::result(res)
-}
-
-#[inline]
-pub fn epoll_ctl<'a, T>(
- epfd: RawFd,
- op: EpollOp,
- fd: RawFd,
- event: T,
-) -> Result<()>
-where
- T: Into<Option<&'a mut EpollEvent>>,
-{
- let mut event: Option<&mut EpollEvent> = event.into();
- if event.is_none() && op != EpollOp::EpollCtlDel {
- Err(Errno::EINVAL)
- } else {
- let res = unsafe {
- if let Some(ref mut event) = event {
- libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event)
- } else {
- libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut())
- }
- };
- Errno::result(res).map(drop)
- }
-}
-
-#[inline]
-pub fn epoll_wait(
- epfd: RawFd,
- events: &mut [EpollEvent],
- timeout_ms: isize,
-) -> Result<usize> {
- let res = unsafe {
- libc::epoll_wait(
- epfd,
- events.as_mut_ptr() as *mut libc::epoll_event,
- events.len() as c_int,
- timeout_ms as c_int,
- )
- };
-
- Errno::result(res).map(|r| r as usize)
-}
diff --git a/vendor/nix/src/sys/event.rs b/vendor/nix/src/sys/event.rs
deleted file mode 100644
index d8ad628ea..000000000
--- a/vendor/nix/src/sys/event.rs
+++ /dev/null
@@ -1,374 +0,0 @@
-/* TOOD: Implement for other kqueue based systems
- */
-
-use crate::{Errno, Result};
-#[cfg(not(target_os = "netbsd"))]
-use libc::{c_int, c_long, intptr_t, time_t, timespec, uintptr_t};
-#[cfg(target_os = "netbsd")]
-use libc::{c_long, intptr_t, size_t, time_t, timespec, uintptr_t};
-use std::convert::TryInto;
-use std::mem;
-use std::os::unix::io::RawFd;
-use std::ptr;
-
-// Redefine kevent in terms of programmer-friendly enums and bitfields.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct KEvent {
- kevent: libc::kevent,
-}
-
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "openbsd"
-))]
-type type_of_udata = *mut libc::c_void;
-#[cfg(any(target_os = "netbsd"))]
-type type_of_udata = intptr_t;
-
-#[cfg(target_os = "netbsd")]
-type type_of_event_filter = u32;
-#[cfg(not(target_os = "netbsd"))]
-type type_of_event_filter = i16;
-libc_enum! {
- #[cfg_attr(target_os = "netbsd", repr(u32))]
- #[cfg_attr(not(target_os = "netbsd"), repr(i16))]
- #[non_exhaustive]
- pub enum EventFilter {
- EVFILT_AIO,
- /// Returns whenever there is no remaining data in the write buffer
- #[cfg(target_os = "freebsd")]
- EVFILT_EMPTY,
- #[cfg(target_os = "dragonfly")]
- EVFILT_EXCEPT,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))]
- EVFILT_FS,
- #[cfg(target_os = "freebsd")]
- EVFILT_LIO,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- EVFILT_MACHPORT,
- EVFILT_PROC,
- /// Returns events associated with the process referenced by a given
- /// process descriptor, created by `pdfork()`. The events to monitor are:
- ///
- /// - NOTE_EXIT: the process has exited. The exit status will be stored in data.
- #[cfg(target_os = "freebsd")]
- EVFILT_PROCDESC,
- EVFILT_READ,
- /// Returns whenever an asynchronous `sendfile()` call completes.
- #[cfg(target_os = "freebsd")]
- EVFILT_SENDFILE,
- EVFILT_SIGNAL,
- EVFILT_TIMER,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))]
- EVFILT_USER,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- EVFILT_VM,
- EVFILT_VNODE,
- EVFILT_WRITE,
- }
- impl TryFrom<type_of_event_filter>
-}
-
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "openbsd"
-))]
-pub type type_of_event_flag = u16;
-#[cfg(any(target_os = "netbsd"))]
-pub type type_of_event_flag = u32;
-libc_bitflags! {
- pub struct EventFlag: type_of_event_flag {
- EV_ADD;
- EV_CLEAR;
- EV_DELETE;
- EV_DISABLE;
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
- EV_DISPATCH;
- #[cfg(target_os = "freebsd")]
- EV_DROP;
- EV_ENABLE;
- EV_EOF;
- EV_ERROR;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EV_FLAG0;
- EV_FLAG1;
- #[cfg(target_os = "dragonfly")]
- EV_NODATA;
- EV_ONESHOT;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EV_OOBAND;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- EV_POLL;
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
- EV_RECEIPT;
- }
-}
-
-libc_bitflags!(
- pub struct FilterFlag: u32 {
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_ABSOLUTE;
- NOTE_ATTRIB;
- NOTE_CHILD;
- NOTE_DELETE;
- #[cfg(target_os = "openbsd")]
- NOTE_EOF;
- NOTE_EXEC;
- NOTE_EXIT;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_EXITSTATUS;
- NOTE_EXTEND;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFAND;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFCOPY;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFCTRLMASK;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFLAGSMASK;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFNOP;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_FFOR;
- NOTE_FORK;
- NOTE_LINK;
- NOTE_LOWAT;
- #[cfg(target_os = "freebsd")]
- NOTE_MSECONDS;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_NONE;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
- NOTE_NSECONDS;
- #[cfg(target_os = "dragonfly")]
- NOTE_OOB;
- NOTE_PCTRLMASK;
- NOTE_PDATAMASK;
- NOTE_RENAME;
- NOTE_REVOKE;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
- NOTE_SECONDS;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_SIGNAL;
- NOTE_TRACK;
- NOTE_TRACKERR;
- #[cfg(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly"))]
- NOTE_TRIGGER;
- #[cfg(target_os = "openbsd")]
- NOTE_TRUNCATE;
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
- NOTE_USECONDS;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_VM_ERROR;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_VM_PRESSURE;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_VM_PRESSURE_SUDDEN_TERMINATE;
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- NOTE_VM_PRESSURE_TERMINATE;
- NOTE_WRITE;
- }
-);
-
-pub fn kqueue() -> Result<RawFd> {
- let res = unsafe { libc::kqueue() };
-
- Errno::result(res)
-}
-
-// KEvent can't derive Send because on some operating systems, udata is defined
-// as a void*. However, KEvent's public API always treats udata as an intptr_t,
-// which is safe to Send.
-unsafe impl Send for KEvent {}
-
-impl KEvent {
- #[allow(clippy::needless_update)] // Not needless on all platforms.
- pub fn new(
- ident: uintptr_t,
- filter: EventFilter,
- flags: EventFlag,
- fflags: FilterFlag,
- data: intptr_t,
- udata: intptr_t,
- ) -> KEvent {
- KEvent {
- kevent: libc::kevent {
- ident,
- filter: filter as type_of_event_filter,
- flags: flags.bits(),
- fflags: fflags.bits(),
- // data can be either i64 or intptr_t, depending on platform
- data: data as _,
- udata: udata as type_of_udata,
- ..unsafe { mem::zeroed() }
- },
- }
- }
-
- pub fn ident(&self) -> uintptr_t {
- self.kevent.ident
- }
-
- pub fn filter(&self) -> Result<EventFilter> {
- self.kevent.filter.try_into()
- }
-
- pub fn flags(&self) -> EventFlag {
- EventFlag::from_bits(self.kevent.flags).unwrap()
- }
-
- pub fn fflags(&self) -> FilterFlag {
- FilterFlag::from_bits(self.kevent.fflags).unwrap()
- }
-
- pub fn data(&self) -> intptr_t {
- self.kevent.data as intptr_t
- }
-
- pub fn udata(&self) -> intptr_t {
- self.kevent.udata as intptr_t
- }
-}
-
-pub fn kevent(
- kq: RawFd,
- changelist: &[KEvent],
- eventlist: &mut [KEvent],
- timeout_ms: usize,
-) -> Result<usize> {
- // Convert ms to timespec
- let timeout = timespec {
- tv_sec: (timeout_ms / 1000) as time_t,
- tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long,
- };
-
- kevent_ts(kq, changelist, eventlist, Some(timeout))
-}
-
-#[cfg(any(
- target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "openbsd"
-))]
-type type_of_nchanges = c_int;
-#[cfg(target_os = "netbsd")]
-type type_of_nchanges = size_t;
-
-pub fn kevent_ts(
- kq: RawFd,
- changelist: &[KEvent],
- eventlist: &mut [KEvent],
- timeout_opt: Option<timespec>,
-) -> Result<usize> {
- let res = unsafe {
- libc::kevent(
- kq,
- changelist.as_ptr() as *const libc::kevent,
- changelist.len() as type_of_nchanges,
- eventlist.as_mut_ptr() as *mut libc::kevent,
- eventlist.len() as type_of_nchanges,
- if let Some(ref timeout) = timeout_opt {
- timeout as *const timespec
- } else {
- ptr::null()
- },
- )
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-#[inline]
-pub fn ev_set(
- ev: &mut KEvent,
- ident: usize,
- filter: EventFilter,
- flags: EventFlag,
- fflags: FilterFlag,
- udata: intptr_t,
-) {
- ev.kevent.ident = ident as uintptr_t;
- ev.kevent.filter = filter as type_of_event_filter;
- ev.kevent.flags = flags.bits();
- ev.kevent.fflags = fflags.bits();
- ev.kevent.data = 0;
- ev.kevent.udata = udata as type_of_udata;
-}
-
-#[test]
-fn test_struct_kevent() {
- use std::mem;
-
- let udata: intptr_t = 12345;
-
- let actual = KEvent::new(
- 0xdead_beef,
- EventFilter::EVFILT_READ,
- EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
- FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
- 0x1337,
- udata,
- );
- assert_eq!(0xdead_beef, actual.ident());
- let filter = actual.kevent.filter;
- assert_eq!(libc::EVFILT_READ, filter);
- assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
- assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
- assert_eq!(0x1337, actual.data());
- assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata);
- assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
-}
-
-#[test]
-fn test_kevent_filter() {
- let udata: intptr_t = 12345;
-
- let actual = KEvent::new(
- 0xdead_beef,
- EventFilter::EVFILT_READ,
- EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
- FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
- 0x1337,
- udata,
- );
- assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
-}
diff --git a/vendor/nix/src/sys/eventfd.rs b/vendor/nix/src/sys/eventfd.rs
deleted file mode 100644
index cd906720c..000000000
--- a/vendor/nix/src/sys/eventfd.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-use crate::errno::Errno;
-use crate::Result;
-use std::os::unix::io::RawFd;
-
-libc_bitflags! {
- pub struct EfdFlags: libc::c_int {
- EFD_CLOEXEC; // Since Linux 2.6.27
- EFD_NONBLOCK; // Since Linux 2.6.27
- EFD_SEMAPHORE; // Since Linux 2.6.30
- }
-}
-
-pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> {
- let res = unsafe { libc::eventfd(initval, flags.bits()) };
-
- Errno::result(res).map(|r| r as RawFd)
-}
diff --git a/vendor/nix/src/sys/inotify.rs b/vendor/nix/src/sys/inotify.rs
deleted file mode 100644
index 84356ec70..000000000
--- a/vendor/nix/src/sys/inotify.rs
+++ /dev/null
@@ -1,248 +0,0 @@
-//! Monitoring API for filesystem events.
-//!
-//! Inotify is a Linux-only API to monitor filesystems events.
-//!
-//! 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":
-//! ```no_run
-//! # use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify};
-//! #
-//! // We create a new inotify instance.
-//! let instance = Inotify::init(InitFlags::empty()).unwrap();
-//!
-//! // We add a new watch on directory "test" for all events.
-//! let wd = instance.add_watch("test", AddWatchFlags::IN_ALL_EVENTS).unwrap();
-//!
-//! loop {
-//! // We read from our inotify instance for events.
-//! let events = instance.read_events().unwrap();
-//! println!("Events: {:?}", events);
-//! }
-//! ```
-
-use crate::errno::Errno;
-use crate::unistd::read;
-use crate::NixPath;
-use crate::Result;
-use cfg_if::cfg_if;
-use libc::{c_char, c_int};
-use std::ffi::{CStr, OsStr, OsString};
-use std::mem::{size_of, MaybeUninit};
-use std::os::unix::ffi::OsStrExt;
-use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
-use std::ptr;
-
-libc_bitflags! {
- /// Configuration options for [`inotify_add_watch`](fn.inotify_add_watch.html).
- pub struct AddWatchFlags: u32 {
- /// File was accessed.
- IN_ACCESS;
- /// File was modified.
- IN_MODIFY;
- /// Metadata changed.
- IN_ATTRIB;
- /// Writable file was closed.
- IN_CLOSE_WRITE;
- /// Nonwritable file was closed.
- IN_CLOSE_NOWRITE;
- /// File was opened.
- IN_OPEN;
- /// File was moved from X.
- IN_MOVED_FROM;
- /// File was moved to Y.
- IN_MOVED_TO;
- /// Subfile was created.
- IN_CREATE;
- /// Subfile was deleted.
- IN_DELETE;
- /// Self was deleted.
- IN_DELETE_SELF;
- /// Self was moved.
- IN_MOVE_SELF;
-
- /// Backing filesystem was unmounted.
- IN_UNMOUNT;
- /// Event queue overflowed.
- IN_Q_OVERFLOW;
- /// File was ignored.
- IN_IGNORED;
-
- /// Combination of `IN_CLOSE_WRITE` and `IN_CLOSE_NOWRITE`.
- IN_CLOSE;
- /// Combination of `IN_MOVED_FROM` and `IN_MOVED_TO`.
- IN_MOVE;
-
- /// Only watch the path if it is a directory.
- IN_ONLYDIR;
- /// Don't follow symlinks.
- IN_DONT_FOLLOW;
-
- /// Event occurred against directory.
- IN_ISDIR;
- /// Only send event once.
- IN_ONESHOT;
- /// All of the events.
- IN_ALL_EVENTS;
- }
-}
-
-libc_bitflags! {
- /// Configuration options for [`inotify_init1`](fn.inotify_init1.html).
- pub struct InitFlags: c_int {
- /// Set the `FD_CLOEXEC` flag on the file descriptor.
- IN_CLOEXEC;
- /// Set the `O_NONBLOCK` flag on the open file description referred to by the new file descriptor.
- IN_NONBLOCK;
- }
-}
-
-/// An inotify instance. This is also a file descriptor, you can feed it to
-/// other interfaces consuming file descriptors, epoll for example.
-#[derive(Debug, Clone, Copy)]
-pub struct Inotify {
- fd: RawFd,
-}
-
-/// 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.
-#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
-pub struct WatchDescriptor {
- wd: i32,
-}
-
-/// A single inotify event.
-///
-/// 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.
- 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.
- pub cookie: u32,
- /// Filename. This field exists only if the event was triggered for a file
- /// inside the watched directory.
- pub name: Option<OsString>,
-}
-
-impl Inotify {
- /// Initialize a new inotify instance.
- ///
- /// Returns a Result containing an inotify instance.
- ///
- /// 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()) });
-
- res.map(|fd| Inotify { fd })
- }
-
- /// Adds a new watch on the target file or directory.
- ///
- /// Returns a watch descriptor. This is not a File Descriptor!
- ///
- /// 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,
- ) -> Result<WatchDescriptor> {
- let res = path.with_nix_path(|cstr| unsafe {
- libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
- })?;
-
- Errno::result(res).map(|wd| WatchDescriptor { wd })
- }
-
- /// Removes an existing watch using the watch descriptor returned by
- /// inotify_add_watch.
- ///
- /// Returns an EINVAL error if the watch descriptor is invalid.
- ///
- /// For more information see, [inotify_rm_watch(2)](https://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
- pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
- cfg_if! {
- if #[cfg(target_os = "linux")] {
- let arg = wd.wd;
- } else if #[cfg(target_os = "android")] {
- let arg = wd.wd as u32;
- }
- }
- let res = unsafe { libc::inotify_rm_watch(self.fd, arg) };
-
- Errno::result(res).map(drop)
- }
-
- /// 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.
- ///
- /// 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>> {
- let header_size = size_of::<libc::inotify_event>();
- const BUFSIZ: usize = 4096;
- let mut buffer = [0u8; BUFSIZ];
- let mut events = Vec::new();
- let mut offset = 0;
-
- let nread = read(self.fd, &mut buffer)?;
-
- while (nread - offset) >= header_size {
- let event = unsafe {
- let mut event = MaybeUninit::<libc::inotify_event>::uninit();
- ptr::copy_nonoverlapping(
- buffer.as_ptr().add(offset),
- event.as_mut_ptr() as *mut u8,
- (BUFSIZ - offset).min(header_size),
- );
- event.assume_init()
- };
-
- let name = match event.len {
- 0 => None,
- _ => {
- 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())
- }
- };
-
- events.push(InotifyEvent {
- wd: WatchDescriptor { wd: event.wd },
- mask: AddWatchFlags::from_bits_truncate(event.mask),
- cookie: event.cookie,
- name,
- });
-
- offset += header_size + event.len as usize;
- }
-
- Ok(events)
- }
-}
-
-impl AsRawFd for Inotify {
- fn as_raw_fd(&self) -> RawFd {
- self.fd
- }
-}
-
-impl FromRawFd for Inotify {
- unsafe fn from_raw_fd(fd: RawFd) -> Self {
- Inotify { fd }
- }
-}
diff --git a/vendor/nix/src/sys/ioctl/bsd.rs b/vendor/nix/src/sys/ioctl/bsd.rs
deleted file mode 100644
index 307994cb9..000000000
--- a/vendor/nix/src/sys/ioctl/bsd.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-/// 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;
-
-mod consts {
- use crate::sys::ioctl::ioctl_num_type;
- #[doc(hidden)]
- pub const VOID: ioctl_num_type = 0x2000_0000;
- #[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;
- #[doc(hidden)]
- pub const IOCPARM_MASK: ioctl_num_type = 0x1fff;
-}
-
-pub use self::consts::*;
-
-#[macro_export]
-#[doc(hidden)]
-macro_rules! ioc {
- ($inout:expr, $group:expr, $num:expr, $len:expr) => {
- $inout
- | (($len as $crate::sys::ioctl::ioctl_num_type
- & $crate::sys::ioctl::IOCPARM_MASK)
- << 16)
- | (($group as $crate::sys::ioctl::ioctl_num_type) << 8)
- | ($num as $crate::sys::ioctl::ioctl_num_type)
- };
-}
-
-/// Generate an ioctl request code for a command that passes no data.
-///
-/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_none!()` directly.
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// const KVMIO: u8 = 0xAE;
-/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_none {
- ($g:expr, $n:expr) => {
- ioc!($crate::sys::ioctl::VOID, $g, $n, 0)
- };
-}
-
-/// Generate an ioctl request code for a command that passes an integer
-///
-/// This is equivalent to the `_IOWINT()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_write_int!()` directly.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_write_int {
- ($g:expr, $n:expr) => {
- ioc!(
- $crate::sys::ioctl::VOID,
- $g,
- $n,
- ::std::mem::size_of::<$crate::libc::c_int>()
- )
- };
-}
-
-/// Generate an ioctl request code for a command that reads.
-///
-/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_read!()` directly.
-///
-/// The read/write direction is relative to userland, so this
-/// command would be userland is reading and the kernel is
-/// writing.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_read {
- ($g:expr, $n:expr, $len:expr) => {
- ioc!($crate::sys::ioctl::OUT, $g, $n, $len)
- };
-}
-
-/// Generate an ioctl request code for a command that writes.
-///
-/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_write!()` directly.
-///
-/// The read/write direction is relative to userland, so this
-/// command would be userland is writing and the kernel is
-/// reading.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_write {
- ($g:expr, $n:expr, $len:expr) => {
- ioc!($crate::sys::ioctl::IN, $g, $n, $len)
- };
-}
-
-/// Generate an ioctl request code for a command that reads and writes.
-///
-/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_readwrite {
- ($g:expr, $n:expr, $len:expr) => {
- ioc!($crate::sys::ioctl::INOUT, $g, $n, $len)
- };
-}
diff --git a/vendor/nix/src/sys/ioctl/linux.rs b/vendor/nix/src/sys/ioctl/linux.rs
deleted file mode 100644
index 0c0a20905..000000000
--- a/vendor/nix/src/sys/ioctl/linux.rs
+++ /dev/null
@@ -1,172 +0,0 @@
-/// The datatype used for the ioctl number
-#[cfg(any(target_os = "android", target_env = "musl"))]
-#[doc(hidden)]
-pub type ioctl_num_type = ::libc::c_int;
-#[cfg(not(any(target_os = "android", target_env = "musl")))]
-#[doc(hidden)]
-pub type ioctl_num_type = ::libc::c_ulong;
-/// The datatype used for the 3rd argument
-#[doc(hidden)]
-pub type ioctl_param_type = ::libc::c_ulong;
-
-#[doc(hidden)]
-pub const NRBITS: ioctl_num_type = 8;
-#[doc(hidden)]
-pub const TYPEBITS: ioctl_num_type = 8;
-
-#[cfg(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc",
- target_arch = "powerpc64",
- target_arch = "sparc64"
-))]
-mod consts {
- #[doc(hidden)]
- pub const NONE: u8 = 1;
- #[doc(hidden)]
- pub const READ: u8 = 2;
- #[doc(hidden)]
- pub const WRITE: u8 = 4;
- #[doc(hidden)]
- pub const SIZEBITS: u8 = 13;
- #[doc(hidden)]
- pub const DIRBITS: u8 = 3;
-}
-
-// "Generic" ioctl protocol
-#[cfg(any(
- target_arch = "x86",
- target_arch = "arm",
- target_arch = "s390x",
- target_arch = "x86_64",
- target_arch = "aarch64",
- target_arch = "riscv32",
- target_arch = "riscv64"
-))]
-mod consts {
- #[doc(hidden)]
- pub const NONE: u8 = 0;
- #[doc(hidden)]
- pub const READ: u8 = 2;
- #[doc(hidden)]
- pub const WRITE: u8 = 1;
- #[doc(hidden)]
- pub const SIZEBITS: u8 = 14;
- #[doc(hidden)]
- pub const DIRBITS: u8 = 2;
-}
-
-pub use self::consts::*;
-
-#[doc(hidden)]
-pub const NRSHIFT: ioctl_num_type = 0;
-#[doc(hidden)]
-pub const TYPESHIFT: ioctl_num_type = NRSHIFT + NRBITS as ioctl_num_type;
-#[doc(hidden)]
-pub const SIZESHIFT: ioctl_num_type = TYPESHIFT + TYPEBITS as ioctl_num_type;
-#[doc(hidden)]
-pub const DIRSHIFT: ioctl_num_type = SIZESHIFT + SIZEBITS as ioctl_num_type;
-
-#[doc(hidden)]
-pub const NRMASK: ioctl_num_type = (1 << NRBITS) - 1;
-#[doc(hidden)]
-pub const TYPEMASK: ioctl_num_type = (1 << TYPEBITS) - 1;
-#[doc(hidden)]
-pub const SIZEMASK: ioctl_num_type = (1 << SIZEBITS) - 1;
-#[doc(hidden)]
-pub const DIRMASK: ioctl_num_type = (1 << DIRBITS) - 1;
-
-/// Encode an ioctl command.
-#[macro_export]
-#[doc(hidden)]
-macro_rules! ioc {
- ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => {
- (($dir as $crate::sys::ioctl::ioctl_num_type
- & $crate::sys::ioctl::DIRMASK)
- << $crate::sys::ioctl::DIRSHIFT)
- | (($ty as $crate::sys::ioctl::ioctl_num_type
- & $crate::sys::ioctl::TYPEMASK)
- << $crate::sys::ioctl::TYPESHIFT)
- | (($nr as $crate::sys::ioctl::ioctl_num_type
- & $crate::sys::ioctl::NRMASK)
- << $crate::sys::ioctl::NRSHIFT)
- | (($sz as $crate::sys::ioctl::ioctl_num_type
- & $crate::sys::ioctl::SIZEMASK)
- << $crate::sys::ioctl::SIZESHIFT)
- };
-}
-
-/// Generate an ioctl request code for a command that passes no data.
-///
-/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_none!()` directly.
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// const KVMIO: u8 = 0xAE;
-/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_none {
- ($ty:expr, $nr:expr) => {
- ioc!($crate::sys::ioctl::NONE, $ty, $nr, 0)
- };
-}
-
-/// Generate an ioctl request code for a command that reads.
-///
-/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_read!()` directly.
-///
-/// The read/write direction is relative to userland, so this
-/// command would be userland is reading and the kernel is
-/// writing.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_read {
- ($ty:expr, $nr:expr, $sz:expr) => {
- ioc!($crate::sys::ioctl::READ, $ty, $nr, $sz)
- };
-}
-
-/// Generate an ioctl request code for a command that writes.
-///
-/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_write!()` directly.
-///
-/// The read/write direction is relative to userland, so this
-/// command would be userland is writing and the kernel is
-/// reading.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_write {
- ($ty:expr, $nr:expr, $sz:expr) => {
- ioc!($crate::sys::ioctl::WRITE, $ty, $nr, $sz)
- };
-}
-
-/// Generate an ioctl request code for a command that reads and writes.
-///
-/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
-///
-/// You should only use this macro directly if the `ioctl` you're working
-/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
-#[macro_export(local_inner_macros)]
-macro_rules! request_code_readwrite {
- ($ty:expr, $nr:expr, $sz:expr) => {
- ioc!(
- $crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE,
- $ty,
- $nr,
- $sz
- )
- };
-}
diff --git a/vendor/nix/src/sys/ioctl/mod.rs b/vendor/nix/src/sys/ioctl/mod.rs
deleted file mode 100644
index 98d6b5c99..000000000
--- a/vendor/nix/src/sys/ioctl/mod.rs
+++ /dev/null
@@ -1,786 +0,0 @@
-//! Provide helpers for making ioctl system calls.
-//!
-//! This library is pretty low-level and messy. `ioctl` is not fun.
-//!
-//! What is an `ioctl`?
-//! ===================
-//!
-//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want to add a new
-//! syscall? Make it an `ioctl`! `ioctl` refers to both the syscall, and the commands that can be
-//! sent with it. `ioctl` stands for "IO control", and the commands are always sent to a file
-//! descriptor.
-//!
-//! It is common to see `ioctl`s used for the following purposes:
-//!
-//! * Provide read/write access to out-of-band data related to a device such as configuration
-//! (for instance, setting serial port options)
-//! * Provide a mechanism for performing full-duplex data transfers (for instance, xfer on SPI
-//! devices).
-//! * Provide access to control functions on a device (for example, on Linux you can send
-//! commands like pause, resume, and eject to the CDROM device.
-//! * Do whatever else the device driver creator thought made most sense.
-//!
-//! `ioctl`s are synchronous system calls and are similar to read and write calls in that regard.
-//! They operate on file descriptors and have an identifier that specifies what the ioctl is.
-//! Additionally they may read or write data and therefore need to pass along a data pointer.
-//! Besides the semantics of the ioctls being confusing, the generation of this identifer can also
-//! be difficult.
-//!
-//! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some
-//! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into
-//! subcomponents (For linux this is documented in
-//! [`Documentation/ioctl/ioctl-number.rst`](https://elixir.bootlin.com/linux/latest/source/Documentation/userspace-api/ioctl/ioctl-number.rst)):
-//!
-//! * Number: The actual ioctl ID
-//! * Type: A grouping of ioctls for a common purpose or driver
-//! * Size: The size in bytes of the data that will be transferred
-//! * Direction: Whether there is any data and if it's read, write, or both
-//!
-//! Newer drivers should not generate complete integer identifiers for their `ioctl`s instead
-//! preferring to use the 4 components above to generate the final ioctl identifier. Because of
-//! how old `ioctl`s are, however, there are many hard-coded `ioctl` identifiers. These are
-//! commonly referred to as "bad" in `ioctl` documentation.
-//!
-//! Defining `ioctl`s
-//! =================
-//!
-//! This library provides several `ioctl_*!` macros for binding `ioctl`s. These generate public
-//! unsafe functions that can then be used for calling the ioctl. This macro has a few different
-//! ways it can be used depending on the specific ioctl you're working with.
-//!
-//! A simple `ioctl` is `SPI_IOC_RD_MODE`. This ioctl works with the SPI interface on Linux. This
-//! specific `ioctl` reads the mode of the SPI device as a `u8`. It's declared in
-//! `/include/uapi/linux/spi/spidev.h` as `_IOR(SPI_IOC_MAGIC, 1, __u8)`. Since it uses the `_IOR`
-//! macro, we know it's a `read` ioctl and can use the `ioctl_read!` macro as follows:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-//! const SPI_IOC_TYPE_MODE: u8 = 1;
-//! ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
-//! # fn main() {}
-//! ```
-//!
-//! This generates the function:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! # use std::mem;
-//! # use nix::{libc, Result};
-//! # use nix::errno::Errno;
-//! # use nix::libc::c_int as c_int;
-//! # const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-//! # const SPI_IOC_TYPE_MODE: u8 = 1;
-//! pub unsafe fn spi_read_mode(fd: c_int, data: *mut u8) -> Result<c_int> {
-//! let res = libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data);
-//! Errno::result(res)
-//! }
-//! # fn main() {}
-//! ```
-//!
-//! The return value for the wrapper functions generated by the `ioctl_*!` macros are `nix::Error`s.
-//! These are generated by assuming the return value of the ioctl is `-1` on error and everything
-//! else is a valid return value. If this is not the case, `Result::map` can be used to map some
-//! of the range of "good" values (-Inf..-2, 0..Inf) into a smaller range in a helper function.
-//!
-//! Writing `ioctl`s generally use pointers as their data source and these should use the
-//! `ioctl_write_ptr!`. But in some cases an `int` is passed directly. For these `ioctl`s use the
-//! `ioctl_write_int!` macro. This variant does not take a type as the last argument:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! const HCI_IOC_MAGIC: u8 = b'k';
-//! const HCI_IOC_HCIDEVUP: u8 = 1;
-//! ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
-//! # fn main() {}
-//! ```
-//!
-//! Some `ioctl`s don't transfer any data, and those should use `ioctl_none!`. This macro
-//! doesn't take a type and so it is declared similar to the `write_int` variant shown above.
-//!
-//! The mode for a given `ioctl` should be clear from the documentation if it has good
-//! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl`
-//! number where `_IO`, `_IOR`, `_IOW`, and `_IOWR` map to "none", "read", "write_*", and "readwrite"
-//! 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](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
-//! --------------------
-//!
-//! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of
-//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the
-//! `ioctl_*_bad!` macros. This naming comes from the Linux kernel which refers to these
-//! `ioctl`s as "bad". These are a different variant as they bypass calling the macro that generates
-//! the ioctl number and instead use the defined value directly.
-//!
-//! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor.
-//! It's defined as `0x5401` in `ioctls.h` on Linux and can be implemented as:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! # #[cfg(any(target_os = "android", target_os = "linux"))]
-//! # use nix::libc::TCGETS as TCGETS;
-//! # #[cfg(any(target_os = "android", target_os = "linux"))]
-//! # use nix::libc::termios as termios;
-//! # #[cfg(any(target_os = "android", target_os = "linux"))]
-//! ioctl_read_bad!(tcgets, TCGETS, termios);
-//! # fn main() {}
-//! ```
-//!
-//! The generated function has the same form as that generated by `ioctl_read!`:
-//!
-//! ```text
-//! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result<c_int>;
-//! ```
-//!
-//! Working with Arrays
-//! -------------------
-//!
-//! Some `ioctl`s work with entire arrays of elements. These are supported by the `ioctl_*_buf`
-//! family of macros: `ioctl_read_buf`, `ioctl_write_buf`, and `ioctl_readwrite_buf`. Note that
-//! there are no "bad" versions for working with buffers. The generated functions include a `len`
-//! argument to specify the number of elements (where the type of each element is specified in the
-//! macro).
-//!
-//! Again looking to the SPI `ioctl`s on Linux for an example, there is a `SPI_IOC_MESSAGE` `ioctl`
-//! that queues up multiple SPI messages by writing an entire array of `spi_ioc_transfer` structs.
-//! `linux/spi/spidev.h` defines a macro to calculate the `ioctl` number like:
-//!
-//! ```C
-//! #define SPI_IOC_MAGIC 'k'
-//! #define SPI_MSGSIZE(N) ...
-//! #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
-//! ```
-//!
-//! The `SPI_MSGSIZE(N)` calculation is already handled by the `ioctl_*!` macros, so all that's
-//! needed to define this `ioctl` is:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-//! const SPI_IOC_TYPE_MESSAGE: u8 = 0;
-//! # pub struct spi_ioc_transfer(u64);
-//! ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
-//! # fn main() {}
-//! ```
-//!
-//! This generates a function like:
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! # use std::mem;
-//! # use nix::{libc, Result};
-//! # use nix::errno::Errno;
-//! # use nix::libc::c_int as c_int;
-//! # const SPI_IOC_MAGIC: u8 = b'k';
-//! # const SPI_IOC_TYPE_MESSAGE: u8 = 0;
-//! # pub struct spi_ioc_transfer(u64);
-//! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result<c_int> {
-//! let res = libc::ioctl(fd,
-//! request_code_write!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()),
-//! data);
-//! Errno::result(res)
-//! }
-//! # fn main() {}
-//! ```
-//!
-//! Finding `ioctl` Documentation
-//! -----------------------------
-//!
-//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
-//! of lines defining macros which use `_IO`, `_IOR`, `_IOW`, `_IOC`, and `_IOWR`. Some `ioctl`s are
-//! documented directly in the headers defining their constants, but others have more extensive
-//! documentation in man pages (like termios' `ioctl`s which are in `tty_ioctl(4)`).
-//!
-//! Documenting the Generated Functions
-//! ===================================
-//!
-//! In many cases, users will wish for the functions generated by the `ioctl`
-//! macro to be public and documented. For this reason, the generated functions
-//! are public by default. If you wish to hide the ioctl, you will need to put
-//! them in a private module.
-//!
-//! For documentation, it is possible to use doc comments inside the `ioctl_*!` macros. Here is an
-//! example :
-//!
-//! ```
-//! # #[macro_use] extern crate nix;
-//! # use nix::libc::c_int;
-//! ioctl_read! {
-//! /// Make the given terminal the controlling terminal of the calling process. The calling
-//! /// process must be a session leader and not have a controlling terminal already. If the
-//! /// terminal is already the controlling terminal of a different session group then the
-//! /// ioctl will fail with **EPERM**, unless the caller is root (more precisely: has the
-//! /// **CAP_SYS_ADMIN** capability) and arg equals 1, in which case the terminal is stolen
-//! /// and all processes that had it as controlling terminal lose it.
-//! tiocsctty, b't', 19, c_int
-//! }
-//!
-//! # fn main() {}
-//! ```
-use cfg_if::cfg_if;
-
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
-#[macro_use]
-mod linux;
-
-#[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "redox"
-))]
-pub use self::linux::*;
-
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"
-))]
-#[macro_use]
-mod bsd;
-
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"
-))]
-pub use self::bsd::*;
-
-/// Convert raw ioctl return value to a Nix result
-#[macro_export]
-#[doc(hidden)]
-macro_rules! convert_ioctl_res {
- ($w:expr) => {{
- $crate::errno::Errno::result($w)
- }};
-}
-
-/// Generates a wrapper function for an ioctl that passes no data to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// The `videodev2` driver on Linux defines the `log_status` `ioctl` as:
-///
-/// ```C
-/// #define VIDIOC_LOG_STATUS _IO('V', 70)
-/// ```
-///
-/// This can be implemented in Rust like:
-///
-/// ```no_run
-/// # #[macro_use] extern crate nix;
-/// ioctl_none!(log_status, b'V', 70);
-/// fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_none {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type))
- }
- )
-}
-
-/// Generates a wrapper function for a "bad" ioctl that passes no data to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```no_run
-/// # #[macro_use] extern crate nix;
-/// # use libc::TIOCNXCL;
-/// # use std::fs::File;
-/// # use std::os::unix::io::AsRawFd;
-/// ioctl_none_bad!(tiocnxcl, TIOCNXCL);
-/// fn main() {
-/// let file = File::open("/dev/ttyUSB0").unwrap();
-/// unsafe { tiocnxcl(file.as_raw_fd()) }.unwrap();
-/// }
-/// ```
-// TODO: add an example using request_code_*!()
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_none_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that reads data from the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-/// const SPI_IOC_TYPE_MODE: u8 = 1;
-/// ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_read {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *mut $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for a "bad" ioctl that reads data from the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # #[cfg(any(target_os = "android", target_os = "linux"))]
-/// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_read_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *mut $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that writes data through a pointer to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # pub struct v4l2_audio {}
-/// ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_write_ptr {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *const $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for a "bad" ioctl that writes data through a pointer to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # #[cfg(any(target_os = "android", target_os = "linux"))]
-/// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_write_ptr_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *const $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-cfg_if! {
- if #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] {
- /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
- ///
- /// The arguments to this macro are:
- ///
- /// * The function name
- /// * The ioctl identifier
- /// * The ioctl sequence number
- ///
- /// The generated function has the following signature:
- ///
- /// ```rust,ignore
- /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
- /// ```
- ///
- /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
- /// * BSD - `libc::c_int`
- /// * Linux - `libc::c_ulong`
- ///
- /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
- ///
- /// # Example
- ///
- /// ```
- /// # #[macro_use] extern crate nix;
- /// ioctl_write_int!(vt_activate, b'v', 4);
- /// # fn main() {}
- /// ```
- #[macro_export(local_inner_macros)]
- macro_rules! ioctl_write_int {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: $crate::sys::ioctl::ioctl_param_type)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
- }
- } else {
- /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
- ///
- /// The arguments to this macro are:
- ///
- /// * The function name
- /// * The ioctl identifier
- /// * The ioctl sequence number
- ///
- /// The generated function has the following signature:
- ///
- /// ```rust,ignore
- /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
- /// ```
- ///
- /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
- /// * BSD - `libc::c_int`
- /// * Linux - `libc::c_ulong`
- ///
- /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
- ///
- /// # Example
- ///
- /// ```
- /// # #[macro_use] extern crate nix;
- /// const HCI_IOC_MAGIC: u8 = b'k';
- /// const HCI_IOC_HCIDEVUP: u8 = 1;
- /// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
- /// # fn main() {}
- /// ```
- #[macro_export(local_inner_macros)]
- macro_rules! ioctl_write_int {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: $crate::sys::ioctl::ioctl_param_type)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
- }
- }
-}
-
-/// Generates a wrapper function for a "bad" ioctl that writes an integer to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Examples
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # #[cfg(any(target_os = "android", target_os = "linux"))]
-/// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK);
-/// # fn main() {}
-/// ```
-///
-/// ```rust
-/// # #[macro_use] extern crate nix;
-/// const KVMIO: u8 = 0xAE;
-/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_write_int_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: $crate::libc::c_int)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that reads and writes data to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Example
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # pub struct v4l2_audio {}
-/// ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_readwrite {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *mut $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for a "bad" ioctl that reads and writes data to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl request code
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-// TODO: Find an example for ioctl_readwrite_bad
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_readwrite_bad {
- ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: *mut $ty)
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that reads an array of elements from the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-// TODO: Find an example for ioctl_read_buf
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_read_buf {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: &mut [$ty])
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that writes an array of elements to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &[DATA_TYPE]) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-///
-/// # Examples
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-/// const SPI_IOC_TYPE_MESSAGE: u8 = 0;
-/// # pub struct spi_ioc_transfer(u64);
-/// ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
-/// # fn main() {}
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_write_buf {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: &[$ty])
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
-
-/// Generates a wrapper function for an ioctl that reads and writes an array of elements to the kernel.
-///
-/// The arguments to this macro are:
-///
-/// * The function name
-/// * The ioctl identifier
-/// * The ioctl sequence number
-/// * The data type passed by this ioctl
-///
-/// The generated function has the following signature:
-///
-/// ```rust,ignore
-/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
-/// ```
-///
-/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-// TODO: Find an example for readwrite_buf
-#[macro_export(local_inner_macros)]
-macro_rules! ioctl_readwrite_buf {
- ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
- $(#[$attr])*
- pub unsafe fn $name(fd: $crate::libc::c_int,
- data: &mut [$ty])
- -> $crate::Result<$crate::libc::c_int> {
- convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
- }
- )
-}
diff --git a/vendor/nix/src/sys/memfd.rs b/vendor/nix/src/sys/memfd.rs
deleted file mode 100644
index ad9345e89..000000000
--- a/vendor/nix/src/sys/memfd.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-//! Interfaces for managing memory-backed files.
-
-use cfg_if::cfg_if;
-use std::os::unix::io::RawFd;
-
-use crate::errno::Errno;
-use crate::Result;
-use std::ffi::CStr;
-
-libc_bitflags!(
- /// Options that change the behavior of [`memfd_create`].
- pub struct MemFdCreateFlag: libc::c_uint {
- /// Set the close-on-exec ([`FD_CLOEXEC`]) flag on the new file descriptor.
- ///
- /// By default, the new file descriptor is set to remain open across an [`execve`]
- /// (the `FD_CLOEXEC` flag is initially disabled). This flag can be used to change
- /// this default. The file offset is set to the beginning of the file (see [`lseek`]).
- ///
- /// See also the description of the `O_CLOEXEC` flag in [`open(2)`].
- ///
- /// [`execve`]: crate::unistd::execve
- /// [`lseek`]: crate::unistd::lseek
- /// [`FD_CLOEXEC`]: crate::fcntl::FdFlag::FD_CLOEXEC
- /// [`open(2)`]: https://man7.org/linux/man-pages/man2/open.2.html
- MFD_CLOEXEC;
- /// Allow sealing operations on this file.
- ///
- /// See also the file sealing notes given in [`memfd_create(2)`].
- ///
- /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
- MFD_ALLOW_SEALING;
- }
-);
-
-/// Creates an anonymous file that lives in memory, and return a file-descriptor to it.
-///
-/// The file behaves like a regular file, and so can be modified, truncated, memory-mapped, and so on.
-/// However, unlike a regular file, it lives in RAM and has a volatile backing storage.
-///
-/// For more information, see [`memfd_create(2)`].
-///
-/// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
-pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
- let res = unsafe {
- cfg_if! {
- if #[cfg(all(
- // Android does not have a memfd_create symbol
- not(target_os = "android"),
- any(
- target_os = "freebsd",
- // If the OS is Linux, gnu and musl expose a memfd_create symbol but not uclibc
- target_env = "gnu",
- target_env = "musl",
- )))]
- {
- libc::memfd_create(name.as_ptr(), flags.bits())
- } else {
- libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
- }
- }
- };
-
- Errno::result(res).map(|r| r as RawFd)
-}
diff --git a/vendor/nix/src/sys/mman.rs b/vendor/nix/src/sys/mman.rs
deleted file mode 100644
index 2bee09161..000000000
--- a/vendor/nix/src/sys/mman.rs
+++ /dev/null
@@ -1,599 +0,0 @@
-//! Memory management declarations.
-
-use crate::errno::Errno;
-#[cfg(not(target_os = "android"))]
-use crate::NixPath;
-use crate::Result;
-#[cfg(not(target_os = "android"))]
-#[cfg(feature = "fs")]
-use crate::{fcntl::OFlag, sys::stat::Mode};
-use libc::{self, c_int, c_void, off_t, size_t};
-use std::{os::unix::io::RawFd, num::NonZeroUsize};
-
-libc_bitflags! {
- /// Desired memory protection of a memory mapping.
- pub struct ProtFlags: c_int {
- /// Pages cannot be accessed.
- PROT_NONE;
- /// Pages can be read.
- PROT_READ;
- /// Pages can be written.
- PROT_WRITE;
- /// Pages can be executed
- PROT_EXEC;
- /// Apply protection up to the end of a mapping that grows upwards.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PROT_GROWSDOWN;
- /// Apply protection down to the beginning of a mapping that grows downwards.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PROT_GROWSUP;
- }
-}
-
-libc_bitflags! {
- /// Additional parameters for [`mmap`].
- pub struct MapFlags: c_int {
- /// Compatibility flag. Ignored.
- MAP_FILE;
- /// Share this mapping. Mutually exclusive with `MAP_PRIVATE`.
- MAP_SHARED;
- /// Create a private copy-on-write mapping. Mutually exclusive with `MAP_SHARED`.
- MAP_PRIVATE;
- /// Place the mapping at exactly the address specified in `addr`.
- MAP_FIXED;
- /// Place the mapping at exactly the address specified in `addr`, but never clobber an existing range.
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_FIXED_NOREPLACE;
- /// To be used with `MAP_FIXED`, to forbid the system
- /// to select a different address than the one specified.
- #[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_EXCL;
- /// Synonym for `MAP_ANONYMOUS`.
- MAP_ANON;
- /// The mapping is not backed by any file.
- MAP_ANONYMOUS;
- /// Put the mapping into the first 2GB of the process address space.
- #[cfg(any(all(any(target_os = "android", target_os = "linux"),
- any(target_arch = "x86", target_arch = "x86_64")),
- all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "x86_64")),
- all(target_os = "freebsd", target_pointer_width = "64")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_32BIT;
- /// Used for stacks; indicates to the kernel that the mapping should extend downward in memory.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_GROWSDOWN;
- /// Compatibility flag. Ignored.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_DENYWRITE;
- /// Compatibility flag. Ignored.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_EXECUTABLE;
- /// Mark the mmaped region to be locked in the same way as `mlock(2)`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_LOCKED;
- /// Do not reserve swap space for this mapping.
- ///
- /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
- #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_NORESERVE;
- /// Populate page tables for a mapping.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_POPULATE;
- /// Only meaningful when used with `MAP_POPULATE`. Don't perform read-ahead.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_NONBLOCK;
- /// Allocate the mapping using "huge pages."
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGETLB;
- /// Make use of 64KB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_64KB;
- /// Make use of 512KB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_512KB;
- /// Make use of 1MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_1MB;
- /// Make use of 2MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_2MB;
- /// Make use of 8MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_8MB;
- /// Make use of 16MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_16MB;
- /// Make use of 32MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_32MB;
- /// Make use of 256MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_256MB;
- /// Make use of 512MB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_512MB;
- /// Make use of 1GB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_1GB;
- /// Make use of 2GB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_2GB;
- /// Make use of 16GB huge page (must be supported by the system)
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HUGE_16GB;
-
- /// Lock the mapped region into memory as with `mlock(2)`.
- #[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_WIRED;
- /// Causes dirtied data in the specified range to be flushed to disk only when necessary.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_NOSYNC;
- /// Rename private pages to a file.
- ///
- /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
- #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_RENAME;
- /// Region may contain semaphores.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_HASSEMAPHORE;
- /// Region grows down, like a stack.
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_STACK;
- /// Pages in this mapping are not retained in the kernel's memory cache.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_NOCACHE;
- /// Allows the W/X bit on the page, it's necessary on aarch64 architecture.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_JIT;
- /// Allows to use large pages, underlying alignment based on size.
- #[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_ALIGNED_SUPER;
- /// Pages will be discarded in the core dumps.
- #[cfg(target_os = "openbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_CONCEAL;
- }
-}
-
-#[cfg(any(target_os = "linux", target_os = "netbsd"))]
-libc_bitflags! {
- /// Options for [`mremap`].
- pub struct MRemapFlags: c_int {
- /// Permit the kernel to relocate the mapping to a new virtual address, if necessary.
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MREMAP_MAYMOVE;
- /// Place the mapping at exactly the address specified in `new_address`.
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MREMAP_FIXED;
- /// Place the mapping at exactly the address specified in `new_address`.
- #[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_FIXED;
- /// Allows to duplicate the mapping to be able to apply different flags on the copy.
- #[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MAP_REMAPDUP;
- }
-}
-
-libc_enum! {
- /// Usage information for a range of memory to allow for performance optimizations by the kernel.
- ///
- /// Used by [`madvise`].
- #[repr(i32)]
- #[non_exhaustive]
- pub enum MmapAdvise {
- /// No further special treatment. This is the default.
- MADV_NORMAL,
- /// Expect random page references.
- MADV_RANDOM,
- /// Expect sequential page references.
- MADV_SEQUENTIAL,
- /// Expect access in the near future.
- MADV_WILLNEED,
- /// Do not expect access in the near future.
- MADV_DONTNEED,
- /// Free up a given range of pages and its associated backing store.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_REMOVE,
- /// Do not make pages in this range available to the child after a `fork(2)`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_DONTFORK,
- /// Undo the effect of `MADV_DONTFORK`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_DOFORK,
- /// Poison the given pages.
- ///
- /// Subsequent references to those pages are treated like hardware memory corruption.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_HWPOISON,
- /// Enable Kernel Samepage Merging (KSM) for the given pages.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_MERGEABLE,
- /// Undo the effect of `MADV_MERGEABLE`
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_UNMERGEABLE,
- /// Preserve the memory of each page but offline the original page.
- #[cfg(any(target_os = "android",
- all(target_os = "linux", any(
- target_arch = "aarch64",
- target_arch = "arm",
- target_arch = "powerpc",
- target_arch = "powerpc64",
- target_arch = "s390x",
- target_arch = "x86",
- target_arch = "x86_64",
- target_arch = "sparc64"))))]
- MADV_SOFT_OFFLINE,
- /// Enable Transparent Huge Pages (THP) for pages in the given range.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_HUGEPAGE,
- /// Undo the effect of `MADV_HUGEPAGE`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_NOHUGEPAGE,
- /// Exclude the given range from a core dump.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_DONTDUMP,
- /// Undo the effect of an earlier `MADV_DONTDUMP`.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_DODUMP,
- /// Specify that the application no longer needs the pages in the given range.
- MADV_FREE,
- /// Request that the system not flush the current range to disk unless it needs to.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_NOSYNC,
- /// Undoes the effects of `MADV_NOSYNC` for any future pages dirtied within the given range.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_AUTOSYNC,
- /// Region is not included in a core file.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_NOCORE,
- /// Include region in a core file
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_CORE,
- /// This process should not be killed when swap space is exhausted.
- #[cfg(any(target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_PROTECT,
- /// Invalidate the hardware page table for the given region.
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_INVAL,
- /// Set the offset of the page directory page to `value` for the virtual page table.
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_SETMAP,
- /// Indicates that the application will not need the data in the given range.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_ZERO_WIRED_PAGES,
- /// Pages can be reused (by anyone).
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_FREE_REUSABLE,
- /// Caller wants to reuse those pages.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MADV_FREE_REUSE,
- // Darwin doesn't document this flag's behavior.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- #[allow(missing_docs)]
- MADV_CAN_REUSE,
- }
-}
-
-libc_bitflags! {
- /// Configuration flags for [`msync`].
- pub struct MsFlags: c_int {
- /// Schedule an update but return immediately.
- MS_ASYNC;
- /// Invalidate all cached data.
- MS_INVALIDATE;
- /// Invalidate pages, but leave them mapped.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MS_KILLPAGES;
- /// Deactivate pages, but leave them mapped.
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MS_DEACTIVATE;
- /// Perform an update and wait for it to complete.
- MS_SYNC;
- }
-}
-
-#[cfg(not(target_os = "haiku"))]
-libc_bitflags! {
- /// Flags for [`mlockall`].
- pub struct MlockAllFlags: c_int {
- /// Lock pages that are currently mapped into the address space of the process.
- MCL_CURRENT;
- /// Lock pages which will become mapped into the address space of the process in the future.
- MCL_FUTURE;
- }
-}
-
-/// Locks all memory pages that contain part of the address range with `length`
-/// bytes starting at `addr`.
-///
-/// Locked pages never move to the swap area.
-///
-/// # Safety
-///
-/// `addr` must meet all the requirements described in the [`mlock(2)`] man page.
-///
-/// [`mlock(2)`]: https://man7.org/linux/man-pages/man2/mlock.2.html
-pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
- Errno::result(libc::mlock(addr, length)).map(drop)
-}
-
-/// Unlocks all memory pages that contain part of the address range with
-/// `length` bytes starting at `addr`.
-///
-/// # Safety
-///
-/// `addr` must meet all the requirements described in the [`munlock(2)`] man
-/// page.
-///
-/// [`munlock(2)`]: https://man7.org/linux/man-pages/man2/munlock.2.html
-pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
- Errno::result(libc::munlock(addr, length)).map(drop)
-}
-
-/// Locks all memory pages mapped into this process' address space.
-///
-/// Locked pages never move to the swap area. For more information, see [`mlockall(2)`].
-///
-/// [`mlockall(2)`]: https://man7.org/linux/man-pages/man2/mlockall.2.html
-#[cfg(not(target_os = "haiku"))]
-pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
- unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
-}
-
-/// Unlocks all memory pages mapped into this process' address space.
-///
-/// For more information, see [`munlockall(2)`].
-///
-/// [`munlockall(2)`]: https://man7.org/linux/man-pages/man2/munlockall.2.html
-#[cfg(not(target_os = "haiku"))]
-pub fn munlockall() -> Result<()> {
- unsafe { Errno::result(libc::munlockall()) }.map(drop)
-}
-
-/// allocate memory, or map files or devices into memory
-///
-/// # Safety
-///
-/// See the [`mmap(2)`] man page for detailed requirements.
-///
-/// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
-pub unsafe fn mmap(
- addr: Option<NonZeroUsize>,
- length: NonZeroUsize,
- prot: ProtFlags,
- flags: MapFlags,
- fd: RawFd,
- offset: off_t,
-) -> Result<*mut c_void> {
- let ptr = addr.map_or(
- std::ptr::null_mut(),
- |a| usize::from(a) as *mut c_void
- );
-
- let ret = libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset);
-
- if ret == libc::MAP_FAILED {
- Err(Errno::last())
- } else {
- Ok(ret)
- }
-}
-
-/// Expands (or shrinks) an existing memory mapping, potentially moving it at
-/// the same time.
-///
-/// # Safety
-///
-/// See the `mremap(2)` [man page](https://man7.org/linux/man-pages/man2/mremap.2.html) for
-/// detailed requirements.
-#[cfg(any(target_os = "linux", target_os = "netbsd"))]
-pub unsafe fn mremap(
- addr: *mut c_void,
- old_size: size_t,
- new_size: size_t,
- flags: MRemapFlags,
- new_address: Option<*mut c_void>,
-) -> Result<*mut c_void> {
- #[cfg(target_os = "linux")]
- let ret = libc::mremap(
- addr,
- old_size,
- new_size,
- flags.bits(),
- new_address.unwrap_or(std::ptr::null_mut()),
- );
- #[cfg(target_os = "netbsd")]
- let ret = libc::mremap(
- addr,
- old_size,
- new_address.unwrap_or(std::ptr::null_mut()),
- new_size,
- flags.bits(),
- );
-
- if ret == libc::MAP_FAILED {
- Err(Errno::last())
- } else {
- Ok(ret)
- }
-}
-
-/// remove a mapping
-///
-/// # Safety
-///
-/// `addr` must meet all the requirements described in the [`munmap(2)`] man
-/// page.
-///
-/// [`munmap(2)`]: https://man7.org/linux/man-pages/man2/munmap.2.html
-pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
- Errno::result(libc::munmap(addr, len)).map(drop)
-}
-
-/// give advice about use of memory
-///
-/// # Safety
-///
-/// See the [`madvise(2)`] man page. Take special care when using
-/// [`MmapAdvise::MADV_FREE`].
-///
-/// [`madvise(2)`]: https://man7.org/linux/man-pages/man2/madvise.2.html
-pub unsafe fn madvise(
- addr: *mut c_void,
- length: size_t,
- advise: MmapAdvise,
-) -> Result<()> {
- Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
-}
-
-/// Set protection of memory mapping.
-///
-/// See [`mprotect(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
-/// details.
-///
-/// # Safety
-///
-/// Calls to `mprotect` are inherently unsafe, as changes to memory protections can lead to
-/// SIGSEGVs.
-///
-/// ```
-/// # use nix::libc::size_t;
-/// # use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags};
-/// # use std::ptr;
-/// const ONE_K: size_t = 1024;
-/// let one_k_non_zero = std::num::NonZeroUsize::new(ONE_K).unwrap();
-/// let mut slice: &mut [u8] = unsafe {
-/// let mem = mmap(None, one_k_non_zero, ProtFlags::PROT_NONE,
-/// MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, -1, 0).unwrap();
-/// mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap();
-/// std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
-/// };
-/// assert_eq!(slice[0], 0x00);
-/// slice[0] = 0xFF;
-/// assert_eq!(slice[0], 0xFF);
-/// ```
-pub unsafe fn mprotect(
- addr: *mut c_void,
- length: size_t,
- prot: ProtFlags,
-) -> Result<()> {
- Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop)
-}
-
-/// synchronize a mapped region
-///
-/// # Safety
-///
-/// `addr` must meet all the requirements described in the [`msync(2)`] man
-/// page.
-///
-/// [`msync(2)`]: https://man7.org/linux/man-pages/man2/msync.2.html
-pub unsafe fn msync(
- addr: *mut c_void,
- length: size_t,
- flags: MsFlags,
-) -> Result<()> {
- Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
-}
-
-#[cfg(not(target_os = "android"))]
-feature! {
-#![feature = "fs"]
-/// Creates and opens a new, or opens an existing, POSIX shared memory object.
-///
-/// For more information, see [`shm_open(3)`].
-///
-/// [`shm_open(3)`]: https://man7.org/linux/man-pages/man3/shm_open.3.html
-pub fn shm_open<P>(
- name: &P,
- flag: OFlag,
- mode: Mode
- ) -> Result<RawFd>
- where P: ?Sized + NixPath
-{
- let ret = name.with_nix_path(|cstr| {
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- unsafe {
- libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint)
- }
- #[cfg(not(any(target_os = "macos", target_os = "ios")))]
- unsafe {
- libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t)
- }
- })?;
-
- Errno::result(ret)
-}
-}
-
-/// Performs the converse of [`shm_open`], removing an object previously created.
-///
-/// For more information, see [`shm_unlink(3)`].
-///
-/// [`shm_unlink(3)`]: https://man7.org/linux/man-pages/man3/shm_unlink.3.html
-#[cfg(not(target_os = "android"))]
-pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
- let ret =
- name.with_nix_path(|cstr| unsafe { libc::shm_unlink(cstr.as_ptr()) })?;
-
- Errno::result(ret).map(drop)
-}
diff --git a/vendor/nix/src/sys/mod.rs b/vendor/nix/src/sys/mod.rs
deleted file mode 100644
index 2065059de..000000000
--- a/vendor/nix/src/sys/mod.rs
+++ /dev/null
@@ -1,228 +0,0 @@
-//! Mostly platform-specific functionality
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- all(target_os = "linux", not(target_env = "uclibc")),
- target_os = "macos",
- target_os = "netbsd"
-))]
-feature! {
- #![feature = "aio"]
- pub mod aio;
-}
-
-feature! {
- #![feature = "event"]
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[allow(missing_docs)]
- pub mod epoll;
-
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[allow(missing_docs)]
- pub mod event;
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[allow(missing_docs)]
- pub mod eventfd;
-}
-
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "redox",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"
-))]
-#[cfg(feature = "ioctl")]
-#[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
-#[macro_use]
-pub mod ioctl;
-
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
-feature! {
- #![feature = "fs"]
- pub mod memfd;
-}
-
-#[cfg(not(target_os = "redox"))]
-feature! {
- #![feature = "mman"]
- pub mod mman;
-}
-
-#[cfg(target_os = "linux")]
-feature! {
- #![feature = "personality"]
- pub mod personality;
-}
-
-feature! {
- #![feature = "pthread"]
- pub mod pthread;
-}
-
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
-feature! {
- #![feature = "ptrace"]
- #[allow(missing_docs)]
- pub mod ptrace;
-}
-
-#[cfg(target_os = "linux")]
-feature! {
- #![feature = "quota"]
- pub mod quota;
-}
-
-#[cfg(target_os = "linux")]
-feature! {
- #![feature = "reboot"]
- pub mod reboot;
-}
-
-#[cfg(not(any(
- target_os = "redox",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "haiku"
-)))]
-feature! {
- #![feature = "resource"]
- pub mod resource;
-}
-
-#[cfg(not(target_os = "redox"))]
-feature! {
- #![feature = "poll"]
- pub mod select;
-}
-
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"
-))]
-feature! {
- #![feature = "zerocopy"]
- pub mod sendfile;
-}
-
-pub mod signal;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-feature! {
- #![feature = "signal"]
- #[allow(missing_docs)]
- pub mod signalfd;
-}
-
-#[cfg(not(target_os = "redox"))]
-feature! {
- #![feature = "socket"]
- #[allow(missing_docs)]
- pub mod socket;
-}
-
-feature! {
- #![feature = "fs"]
- #[allow(missing_docs)]
- pub mod stat;
-}
-
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "openbsd"
-))]
-feature! {
- #![feature = "fs"]
- pub mod statfs;
-}
-
-feature! {
- #![feature = "fs"]
- pub mod statvfs;
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-#[allow(missing_docs)]
-pub mod sysinfo;
-
-feature! {
- #![feature = "term"]
- #[allow(missing_docs)]
- pub mod termios;
-}
-
-#[allow(missing_docs)]
-pub mod time;
-
-feature! {
- #![feature = "uio"]
- pub mod uio;
-}
-
-feature! {
- #![feature = "feature"]
- pub mod utsname;
-}
-
-feature! {
- #![feature = "process"]
- pub mod wait;
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-feature! {
- #![feature = "inotify"]
- pub mod inotify;
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-feature! {
- #![feature = "time"]
- pub mod timerfd;
-}
-
-#[cfg(all(
- any(
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd"
- ),
- feature = "time",
- feature = "signal"
-))]
-feature! {
- #![feature = "time"]
- pub mod timer;
-}
diff --git a/vendor/nix/src/sys/personality.rs b/vendor/nix/src/sys/personality.rs
deleted file mode 100644
index f295a05fa..000000000
--- a/vendor/nix/src/sys/personality.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-//! Process execution domains
-use crate::errno::Errno;
-use crate::Result;
-
-use libc::{self, c_int, c_ulong};
-
-libc_bitflags! {
- /// Flags used and returned by [`get()`](fn.get.html) and
- /// [`set()`](fn.set.html).
- pub struct Persona: c_int {
- /// Provide the legacy virtual address space layout.
- ADDR_COMPAT_LAYOUT;
- /// Disable address-space-layout randomization.
- ADDR_NO_RANDOMIZE;
- /// Limit the address space to 32 bits.
- ADDR_LIMIT_32BIT;
- /// Use `0xc0000000` as the offset at which to search a virtual memory
- /// chunk on [`mmap(2)`], otherwise use `0xffffe000`.
- ///
- /// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
- ADDR_LIMIT_3GB;
- /// User-space function pointers to signal handlers point to descriptors.
- #[cfg(not(any(target_env = "musl", target_env = "uclibc")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- FDPIC_FUNCPTRS;
- /// Map page 0 as read-only.
- MMAP_PAGE_ZERO;
- /// `PROT_READ` implies `PROT_EXEC` for [`mmap(2)`].
- ///
- /// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
- READ_IMPLIES_EXEC;
- /// No effects.
- SHORT_INODE;
- /// [`select(2)`], [`pselect(2)`], and [`ppoll(2)`] do not modify the
- /// returned timeout argument when interrupted by a signal handler.
- ///
- /// [`select(2)`]: https://man7.org/linux/man-pages/man2/select.2.html
- /// [`pselect(2)`]: https://man7.org/linux/man-pages/man2/pselect.2.html
- /// [`ppoll(2)`]: https://man7.org/linux/man-pages/man2/ppoll.2.html
- STICKY_TIMEOUTS;
- /// Have [`uname(2)`] report a 2.6.40+ version number rather than a 3.x
- /// version number.
- ///
- /// [`uname(2)`]: https://man7.org/linux/man-pages/man2/uname.2.html
- #[cfg(not(any(target_env = "musl", target_env = "uclibc")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- UNAME26;
- /// No effects.
- WHOLE_SECONDS;
- }
-}
-
-/// Retrieve the current process personality.
-///
-/// Returns a Result containing a Persona instance.
-///
-/// Example:
-///
-/// ```
-/// # use nix::sys::personality::{self, Persona};
-/// let pers = personality::get().unwrap();
-/// assert!(!pers.contains(Persona::WHOLE_SECONDS));
-/// ```
-pub fn get() -> Result<Persona> {
- let res = unsafe { libc::personality(0xFFFFFFFF) };
-
- Errno::result(res).map(Persona::from_bits_truncate)
-}
-
-/// Set the current process personality.
-///
-/// Returns a Result containing the *previous* personality for the
-/// process, as a Persona.
-///
-/// For more information, see [personality(2)](https://man7.org/linux/man-pages/man2/personality.2.html)
-///
-/// **NOTE**: This call **replaces** the current personality entirely.
-/// To **update** the personality, first call `get()` and then `set()`
-/// with the modified persona.
-///
-/// Example:
-///
-/// ```
-/// # use nix::sys::personality::{self, Persona};
-/// let mut pers = personality::get().unwrap();
-/// assert!(!pers.contains(Persona::ADDR_NO_RANDOMIZE));
-/// personality::set(pers | Persona::ADDR_NO_RANDOMIZE).unwrap();
-/// ```
-pub fn set(persona: Persona) -> Result<Persona> {
- let res = unsafe { libc::personality(persona.bits() as c_ulong) };
-
- Errno::result(res).map(Persona::from_bits_truncate)
-}
diff --git a/vendor/nix/src/sys/pthread.rs b/vendor/nix/src/sys/pthread.rs
deleted file mode 100644
index 6bad03a4d..000000000
--- a/vendor/nix/src/sys/pthread.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-//! Low level threading primitives
-
-#[cfg(not(target_os = "redox"))]
-use crate::errno::Errno;
-#[cfg(not(target_os = "redox"))]
-use crate::Result;
-use libc::{self, pthread_t};
-
-/// Identifies an individual thread.
-pub type Pthread = pthread_t;
-
-/// Obtain ID of the calling thread (see
-/// [`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)`.
-#[inline]
-pub fn pthread_self() -> Pthread {
- unsafe { libc::pthread_self() }
-}
-
-feature! {
-#![feature = "signal"]
-
-/// Send a signal to a thread (see [`pthread_kill(3)`]).
-///
-/// If `signal` is `None`, `pthread_kill` will only preform error checking and
-/// won't send any signal.
-///
-/// [`pthread_kill(3)`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
-#[allow(clippy::not_unsafe_ptr_arg_deref)]
-#[cfg(not(target_os = "redox"))]
-pub fn pthread_kill<T>(thread: Pthread, signal: T) -> Result<()>
- where T: Into<Option<crate::sys::signal::Signal>>
-{
- let sig = match signal.into() {
- Some(s) => s as libc::c_int,
- None => 0,
- };
- let res = unsafe { libc::pthread_kill(thread, sig) };
- Errno::result(res).map(drop)
-}
-}
diff --git a/vendor/nix/src/sys/ptrace/bsd.rs b/vendor/nix/src/sys/ptrace/bsd.rs
deleted file mode 100644
index ba267c657..000000000
--- a/vendor/nix/src/sys/ptrace/bsd.rs
+++ /dev/null
@@ -1,195 +0,0 @@
-use crate::errno::Errno;
-use crate::sys::signal::Signal;
-use crate::unistd::Pid;
-use crate::Result;
-use cfg_if::cfg_if;
-use libc::{self, c_int};
-use std::ptr;
-
-pub type RequestType = c_int;
-
-cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "openbsd"))] {
- #[doc(hidden)]
- pub type AddressType = *mut ::libc::c_char;
- } else {
- #[doc(hidden)]
- pub type AddressType = *mut ::libc::c_void;
- }
-}
-
-libc_enum! {
- #[repr(i32)]
- /// Ptrace Request enum defining the action to be taken.
- #[non_exhaustive]
- pub enum Request {
- PT_TRACE_ME,
- PT_READ_I,
- PT_READ_D,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PT_READ_U,
- PT_WRITE_I,
- PT_WRITE_D,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PT_WRITE_U,
- PT_CONTINUE,
- PT_KILL,
- #[cfg(any(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos"),
- all(target_os = "openbsd", target_arch = "x86_64"),
- all(target_os = "netbsd", any(target_arch = "x86_64",
- target_arch = "powerpc"))))]
- PT_STEP,
- PT_ATTACH,
- PT_DETACH,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PT_SIGEXC,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PT_THUPDATE,
- #[cfg(target_os = "macos")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PT_ATTACHEXC
- }
-}
-
-unsafe fn ptrace_other(
- request: Request,
- pid: Pid,
- addr: AddressType,
- data: c_int,
-) -> Result<c_int> {
- Errno::result(libc::ptrace(
- request as RequestType,
- libc::pid_t::from(pid),
- addr,
- data,
- ))
- .map(|_| 0)
-}
-
-/// Sets the process as traceable, as with `ptrace(PT_TRACEME, ...)`
-///
-/// Indicates that this process is to be traced by its parent.
-/// This is the only ptrace request to be issued by the tracee.
-pub fn traceme() -> Result<()> {
- unsafe {
- ptrace_other(Request::PT_TRACE_ME, Pid::from_raw(0), ptr::null_mut(), 0)
- .map(drop)
- }
-}
-
-/// Attach to a running process, as with `ptrace(PT_ATTACH, ...)`
-///
-/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
-pub fn attach(pid: Pid) -> Result<()> {
- unsafe {
- ptrace_other(Request::PT_ATTACH, pid, ptr::null_mut(), 0).map(drop)
- }
-}
-
-/// Detaches the current running process, as with `ptrace(PT_DETACH, ...)`
-///
-/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a
-/// signal specified by `sig`.
-pub fn detach<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as c_int,
- None => 0,
- };
- unsafe {
- ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), data).map(drop)
- }
-}
-
-/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
-///
-/// Continues the execution of the process with PID `pid`, optionally
-/// delivering a signal specified by `sig`.
-pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as c_int,
- None => 0,
- };
- unsafe {
- // Ignore the useless return value
- ptrace_other(Request::PT_CONTINUE, pid, 1 as AddressType, data)
- .map(drop)
- }
-}
-
-/// Issues a kill request as with `ptrace(PT_KILL, ...)`
-///
-/// This request is equivalent to `ptrace(PT_CONTINUE, ..., SIGKILL);`
-pub fn kill(pid: Pid) -> Result<()> {
- unsafe {
- ptrace_other(Request::PT_KILL, pid, 0 as AddressType, 0).map(drop)
- }
-}
-
-/// Move the stopped tracee process forward by a single step as with
-/// `ptrace(PT_STEP, ...)`
-///
-/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
-/// signal specified by `sig`.
-///
-/// # Example
-/// ```rust
-/// use nix::sys::ptrace::step;
-/// use nix::unistd::Pid;
-/// use nix::sys::signal::Signal;
-/// use nix::sys::wait::*;
-/// // 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(any(
- any(target_os = "dragonfly", target_os = "freebsd", target_os = "macos"),
- all(target_os = "openbsd", target_arch = "x86_64"),
- all(
- target_os = "netbsd",
- any(target_arch = "x86_64", target_arch = "powerpc")
- )
-))]
-pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as c_int,
- None => 0,
- };
- unsafe {
- ptrace_other(Request::PT_STEP, pid, ptr::null_mut(), data).map(drop)
- }
-}
-
-/// Reads a word from a processes memory at the given address
-// Technically, ptrace doesn't dereference the pointer. It passes it directly
-// to the kernel.
-#[allow(clippy::not_unsafe_ptr_arg_deref)]
-pub fn read(pid: Pid, addr: AddressType) -> Result<c_int> {
- unsafe {
- // Traditionally there was a difference between reading data or
- // instruction memory but not in modern systems.
- ptrace_other(Request::PT_READ_D, pid, addr, 0)
- }
-}
-
-/// Writes a word into the processes memory at the given address
-// Technically, ptrace doesn't dereference the pointer. It passes it directly
-// to the kernel.
-#[allow(clippy::not_unsafe_ptr_arg_deref)]
-pub fn write(pid: Pid, addr: AddressType, data: c_int) -> Result<()> {
- unsafe { ptrace_other(Request::PT_WRITE_D, pid, addr, data).map(drop) }
-}
diff --git a/vendor/nix/src/sys/ptrace/linux.rs b/vendor/nix/src/sys/ptrace/linux.rs
deleted file mode 100644
index 9687e05d4..000000000
--- a/vendor/nix/src/sys/ptrace/linux.rs
+++ /dev/null
@@ -1,558 +0,0 @@
-//! For detailed description of the ptrace requests, consult `man ptrace`.
-
-use crate::errno::Errno;
-use crate::sys::signal::Signal;
-use crate::unistd::Pid;
-use crate::Result;
-use cfg_if::cfg_if;
-use libc::{self, c_long, c_void, siginfo_t};
-use std::{mem, ptr};
-
-pub type AddressType = *mut ::libc::c_void;
-
-#[cfg(all(
- target_os = "linux",
- any(
- all(
- target_arch = "x86_64",
- any(target_env = "gnu", target_env = "musl")
- ),
- all(target_arch = "x86", target_env = "gnu")
- )
-))]
-use libc::user_regs_struct;
-
-cfg_if! {
- if #[cfg(any(all(target_os = "linux", target_arch = "s390x"),
- all(target_os = "linux", target_env = "gnu"),
- target_env = "uclibc"))] {
- #[doc(hidden)]
- pub type RequestType = ::libc::c_uint;
- } else {
- #[doc(hidden)]
- pub type RequestType = ::libc::c_int;
- }
-}
-
-libc_enum! {
- #[cfg_attr(not(any(target_env = "musl", target_env = "uclibc", target_os = "android")), repr(u32))]
- #[cfg_attr(any(target_env = "musl", target_env = "uclibc", target_os = "android"), repr(i32))]
- /// Ptrace Request enum defining the action to be taken.
- #[non_exhaustive]
- pub enum Request {
- PTRACE_TRACEME,
- PTRACE_PEEKTEXT,
- PTRACE_PEEKDATA,
- PTRACE_PEEKUSER,
- PTRACE_POKETEXT,
- PTRACE_POKEDATA,
- PTRACE_POKEUSER,
- PTRACE_CONT,
- PTRACE_KILL,
- PTRACE_SINGLESTEP,
- #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
- all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86_64",
- target_pointer_width = "32"))))]
- PTRACE_GETREGS,
- #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
- all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86_64",
- target_pointer_width = "32"))))]
- PTRACE_SETREGS,
- #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
- all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86_64",
- target_pointer_width = "32"))))]
- PTRACE_GETFPREGS,
- #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
- all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86_64",
- target_pointer_width = "32"))))]
- PTRACE_SETFPREGS,
- PTRACE_ATTACH,
- PTRACE_DETACH,
- #[cfg(all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86",
- target_arch = "x86_64")))]
- PTRACE_GETFPXREGS,
- #[cfg(all(target_os = "linux", any(target_env = "musl",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "x86",
- target_arch = "x86_64")))]
- PTRACE_SETFPXREGS,
- PTRACE_SYSCALL,
- PTRACE_SETOPTIONS,
- PTRACE_GETEVENTMSG,
- PTRACE_GETSIGINFO,
- PTRACE_SETSIGINFO,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_GETREGSET,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_SETREGSET,
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PTRACE_SEIZE,
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PTRACE_INTERRUPT,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_LISTEN,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
- PTRACE_PEEKSIGINFO,
- #[cfg(all(target_os = "linux", target_env = "gnu",
- any(target_arch = "x86", target_arch = "x86_64")))]
- PTRACE_SYSEMU,
- #[cfg(all(target_os = "linux", target_env = "gnu",
- any(target_arch = "x86", target_arch = "x86_64")))]
- PTRACE_SYSEMU_SINGLESTEP,
- }
-}
-
-libc_enum! {
- #[repr(i32)]
- /// Using the ptrace options the tracer can configure the tracee to stop
- /// at certain events. This enum is used to define those events as defined
- /// in `man ptrace`.
- #[non_exhaustive]
- pub enum Event {
- /// Event that stops before a return from fork or clone.
- PTRACE_EVENT_FORK,
- /// Event that stops before a return from vfork or clone.
- PTRACE_EVENT_VFORK,
- /// Event that stops before a return from clone.
- PTRACE_EVENT_CLONE,
- /// Event that stops before a return from execve.
- PTRACE_EVENT_EXEC,
- /// Event for a return from vfork.
- PTRACE_EVENT_VFORK_DONE,
- /// Event for a stop before an exit. Unlike the waitpid Exit status program.
- /// registers can still be examined
- PTRACE_EVENT_EXIT,
- /// Stop triggered by a seccomp rule on a tracee.
- PTRACE_EVENT_SECCOMP,
- /// Stop triggered by the `INTERRUPT` syscall, or a group stop,
- /// or when a new child is attached.
- PTRACE_EVENT_STOP,
- }
-}
-
-libc_bitflags! {
- /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
- /// See `man ptrace` for more details.
- pub struct Options: libc::c_int {
- /// When delivering system call traps set a bit to allow tracer to
- /// distinguish between normal stops or syscall stops. May not work on
- /// all systems.
- PTRACE_O_TRACESYSGOOD;
- /// Stop tracee at next fork and start tracing the forked process.
- PTRACE_O_TRACEFORK;
- /// Stop tracee at next vfork call and trace the vforked process.
- PTRACE_O_TRACEVFORK;
- /// Stop tracee at next clone call and trace the cloned process.
- PTRACE_O_TRACECLONE;
- /// Stop tracee at next execve call.
- PTRACE_O_TRACEEXEC;
- /// Stop tracee at vfork completion.
- PTRACE_O_TRACEVFORKDONE;
- /// Stop tracee at next exit call. Stops before exit commences allowing
- /// tracer to see location of exit and register states.
- PTRACE_O_TRACEEXIT;
- /// Stop tracee when a SECCOMP_RET_TRACE rule is triggered. See `man seccomp` for more
- /// details.
- PTRACE_O_TRACESECCOMP;
- /// Send a SIGKILL to the tracee if the tracer exits. This is useful
- /// for ptrace jailers to prevent tracees from escaping their control.
- PTRACE_O_EXITKILL;
- }
-}
-
-fn ptrace_peek(
- request: Request,
- pid: Pid,
- addr: AddressType,
- data: *mut c_void,
-) -> Result<c_long> {
- let ret = unsafe {
- Errno::clear();
- libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
- };
- match Errno::result(ret) {
- Ok(..) | Err(Errno::UnknownErrno) => Ok(ret),
- err @ Err(..) => err,
- }
-}
-
-/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
-#[cfg(all(
- target_os = "linux",
- any(
- all(
- target_arch = "x86_64",
- any(target_env = "gnu", target_env = "musl")
- ),
- all(target_arch = "x86", target_env = "gnu")
- )
-))]
-pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
- ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
-}
-
-/// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
-#[cfg(all(
- target_os = "linux",
- any(
- all(
- target_arch = "x86_64",
- any(target_env = "gnu", target_env = "musl")
- ),
- all(target_arch = "x86", target_env = "gnu")
- )
-))]
-pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
- let res = unsafe {
- libc::ptrace(
- Request::PTRACE_SETREGS as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<c_void>(),
- &regs as *const _ as *const c_void,
- )
- };
- Errno::result(res).map(drop)
-}
-
-/// Function for ptrace requests that return values from the data field.
-/// Some ptrace get requests populate structs or larger elements than `c_long`
-/// and therefore use the data field to return values. This function handles these
-/// requests.
-fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
- let mut data = mem::MaybeUninit::uninit();
- let res = unsafe {
- libc::ptrace(
- request as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<T>(),
- data.as_mut_ptr() as *const _ as *const c_void,
- )
- };
- Errno::result(res)?;
- Ok(unsafe { data.assume_init() })
-}
-
-unsafe fn ptrace_other(
- request: Request,
- pid: Pid,
- addr: AddressType,
- data: *mut c_void,
-) -> Result<c_long> {
- Errno::result(libc::ptrace(
- request as RequestType,
- libc::pid_t::from(pid),
- addr,
- data,
- ))
- .map(|_| 0)
-}
-
-/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
-pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
- let res = unsafe {
- libc::ptrace(
- Request::PTRACE_SETOPTIONS as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<c_void>(),
- options.bits() as *mut c_void,
- )
- };
- Errno::result(res).map(drop)
-}
-
-/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
-pub fn getevent(pid: Pid) -> Result<c_long> {
- ptrace_get_data::<c_long>(Request::PTRACE_GETEVENTMSG, pid)
-}
-
-/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
-pub fn getsiginfo(pid: Pid) -> Result<siginfo_t> {
- ptrace_get_data::<siginfo_t>(Request::PTRACE_GETSIGINFO, pid)
-}
-
-/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
-pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
- let ret = unsafe {
- Errno::clear();
- libc::ptrace(
- Request::PTRACE_SETSIGINFO as RequestType,
- libc::pid_t::from(pid),
- ptr::null_mut::<c_void>(),
- sig as *const _ as *const c_void,
- )
- };
- match Errno::result(ret) {
- Ok(_) => Ok(()),
- Err(e) => Err(e),
- }
-}
-
-/// Sets the process as traceable, as with `ptrace(PTRACE_TRACEME, ...)`
-///
-/// Indicates that this process is to be traced by its parent.
-/// This is the only ptrace request to be issued by the tracee.
-pub fn traceme() -> Result<()> {
- unsafe {
- ptrace_other(
- Request::PTRACE_TRACEME,
- Pid::from_raw(0),
- ptr::null_mut(),
- ptr::null_mut(),
- )
- .map(drop) // ignore the useless return value
- }
-}
-
-/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
-///
-/// Arranges for the tracee to be stopped at the next entry to or exit from a system call,
-/// optionally delivering a signal specified by `sig`.
-pub fn syscall<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(Request::PTRACE_SYSCALL, pid, ptr::null_mut(), data)
- .map(drop) // ignore the useless return value
- }
-}
-
-/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSEMU, ...)`
-///
-/// In contrast to the `syscall` function, the syscall stopped at will not be executed.
-/// Thus the the tracee will only be stopped once per syscall,
-/// optionally delivering a signal specified by `sig`.
-#[cfg(all(
- target_os = "linux",
- target_env = "gnu",
- any(target_arch = "x86", target_arch = "x86_64")
-))]
-pub fn sysemu<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(Request::PTRACE_SYSEMU, pid, ptr::null_mut(), data)
- .map(drop)
- // ignore the useless return value
- }
-}
-
-/// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
-///
-/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
-pub fn attach(pid: Pid) -> Result<()> {
- unsafe {
- ptrace_other(
- Request::PTRACE_ATTACH,
- pid,
- ptr::null_mut(),
- ptr::null_mut(),
- )
- .map(drop) // ignore the useless return value
- }
-}
-
-/// Attach to a running process, as with `ptrace(PTRACE_SEIZE, ...)`
-///
-/// Attaches to the process specified in pid, making it a tracee of the calling process.
-#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn seize(pid: Pid, options: Options) -> Result<()> {
- unsafe {
- ptrace_other(
- Request::PTRACE_SEIZE,
- pid,
- ptr::null_mut(),
- options.bits() as *mut c_void,
- )
- .map(drop) // ignore the useless return value
- }
-}
-
-/// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
-///
-/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a
-/// signal specified by `sig`.
-pub fn detach<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(Request::PTRACE_DETACH, pid, ptr::null_mut(), data)
- .map(drop)
- }
-}
-
-/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
-///
-/// Continues the execution of the process with PID `pid`, optionally
-/// delivering a signal specified by `sig`.
-pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(drop)
- // ignore the useless return value
- }
-}
-
-/// Stop a tracee, as with `ptrace(PTRACE_INTERRUPT, ...)`
-///
-/// This request is equivalent to `ptrace(PTRACE_INTERRUPT, ...)`
-#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn interrupt(pid: Pid) -> Result<()> {
- unsafe {
- ptrace_other(
- Request::PTRACE_INTERRUPT,
- pid,
- ptr::null_mut(),
- ptr::null_mut(),
- )
- .map(drop)
- }
-}
-
-/// Issues a kill request as with `ptrace(PTRACE_KILL, ...)`
-///
-/// This request is equivalent to `ptrace(PTRACE_CONT, ..., SIGKILL);`
-pub fn kill(pid: Pid) -> Result<()> {
- unsafe {
- ptrace_other(
- Request::PTRACE_KILL,
- pid,
- ptr::null_mut(),
- ptr::null_mut(),
- )
- .map(drop)
- }
-}
-
-/// Move the stopped tracee process forward by a single step as with
-/// `ptrace(PTRACE_SINGLESTEP, ...)`
-///
-/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
-/// signal specified by `sig`.
-///
-/// # Example
-/// ```rust
-/// use nix::sys::ptrace::step;
-/// use nix::unistd::Pid;
-/// use nix::sys::signal::Signal;
-/// use nix::sys::wait::*;
-///
-/// // 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);
-/// }
-/// _ => {},
-/// }
-/// ```
-pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(Request::PTRACE_SINGLESTEP, pid, ptr::null_mut(), data)
- .map(drop)
- }
-}
-
-/// Move the stopped tracee process forward by a single step or stop at the next syscall
-/// as with `ptrace(PTRACE_SYSEMU_SINGLESTEP, ...)`
-///
-/// Advances the execution by a single step or until the next syscall.
-/// In case the tracee is stopped at a syscall, the syscall will not be executed.
-/// Optionally, the signal specified by `sig` is delivered to the tracee upon continuation.
-#[cfg(all(
- target_os = "linux",
- target_env = "gnu",
- any(target_arch = "x86", target_arch = "x86_64")
-))]
-pub fn sysemu_step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
- let data = match sig.into() {
- Some(s) => s as i32 as *mut c_void,
- None => ptr::null_mut(),
- };
- unsafe {
- ptrace_other(
- Request::PTRACE_SYSEMU_SINGLESTEP,
- pid,
- ptr::null_mut(),
- data,
- )
- .map(drop) // ignore the useless return value
- }
-}
-
-/// Reads a word from a processes memory at the given address
-pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
- ptrace_peek(Request::PTRACE_PEEKDATA, pid, addr, ptr::null_mut())
-}
-
-/// Writes a word into the processes memory at the given address
-///
-/// # Safety
-///
-/// The `data` argument is passed directly to `ptrace(2)`. Read that man page
-/// for guidance.
-pub unsafe fn write(
- pid: Pid,
- addr: AddressType,
- data: *mut c_void,
-) -> Result<()> {
- ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
-}
-
-/// Reads a word from a user area at `offset`.
-/// The user struct definition can be found in `/usr/include/sys/user.h`.
-pub fn read_user(pid: Pid, offset: AddressType) -> Result<c_long> {
- ptrace_peek(Request::PTRACE_PEEKUSER, pid, offset, ptr::null_mut())
-}
-
-/// Writes a word to a user area at `offset`.
-/// The user struct definition can be found in `/usr/include/sys/user.h`.
-///
-/// # Safety
-///
-/// The `data` argument is passed directly to `ptrace(2)`. Read that man page
-/// for guidance.
-pub unsafe fn write_user(
- pid: Pid,
- offset: AddressType,
- data: *mut c_void,
-) -> Result<()> {
- ptrace_other(Request::PTRACE_POKEUSER, pid, offset, data).map(drop)
-}
diff --git a/vendor/nix/src/sys/ptrace/mod.rs b/vendor/nix/src/sys/ptrace/mod.rs
deleted file mode 100644
index 2b121c0b4..000000000
--- a/vendor/nix/src/sys/ptrace/mod.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-///! Provides helpers for making ptrace system calls
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-mod linux;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::linux::*;
-
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
-mod bsd;
-
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
-pub use self::bsd::*;
diff --git a/vendor/nix/src/sys/quota.rs b/vendor/nix/src/sys/quota.rs
deleted file mode 100644
index b3c44ca70..000000000
--- a/vendor/nix/src/sys/quota.rs
+++ /dev/null
@@ -1,338 +0,0 @@
-//! Set and configure disk quotas for users, groups, or projects.
-//!
-//! # Examples
-//!
-//! Enabling and setting a quota:
-//!
-//! ```rust,no_run
-//! # use nix::sys::quota::{Dqblk, quotactl_on, quotactl_set, QuotaFmt, QuotaType, QuotaValidFlags};
-//! quotactl_on(QuotaType::USRQUOTA, "/dev/sda1", QuotaFmt::QFMT_VFS_V1, "aquota.user").unwrap();
-//! let mut dqblk: Dqblk = Default::default();
-//! dqblk.set_blocks_hard_limit(10000);
-//! dqblk.set_blocks_soft_limit(8000);
-//! quotactl_set(QuotaType::USRQUOTA, "/dev/sda1", 50, &dqblk, QuotaValidFlags::QIF_BLIMITS).unwrap();
-//! ```
-use crate::errno::Errno;
-use crate::{NixPath, Result};
-use libc::{self, c_char, c_int};
-use std::default::Default;
-use std::{mem, ptr};
-
-struct QuotaCmd(QuotaSubCmd, QuotaType);
-
-impl QuotaCmd {
- #[allow(unused_unsafe)]
- fn as_int(&self) -> c_int {
- unsafe { libc::QCMD(self.0 as i32, self.1 as i32) }
- }
-}
-
-// linux quota version >= 2
-libc_enum! {
- #[repr(i32)]
- enum QuotaSubCmd {
- Q_SYNC,
- Q_QUOTAON,
- Q_QUOTAOFF,
- Q_GETQUOTA,
- Q_SETQUOTA,
- }
-}
-
-libc_enum! {
- /// The scope of the quota.
- #[repr(i32)]
- #[non_exhaustive]
- pub enum QuotaType {
- /// Specify a user quota
- USRQUOTA,
- /// Specify a group quota
- GRPQUOTA,
- }
-}
-
-libc_enum! {
- /// The type of quota format to use.
- #[repr(i32)]
- #[non_exhaustive]
- pub enum QuotaFmt {
- /// Use the original quota format.
- QFMT_VFS_OLD,
- /// Use the standard VFS v0 quota format.
- ///
- /// Handles 32-bit UIDs/GIDs and quota limits up to 2<sup>32</sup> bytes/2<sup>32</sup> inodes.
- QFMT_VFS_V0,
- /// Use the VFS v1 quota format.
- ///
- /// Handles 32-bit UIDs/GIDs and quota limits of 2<sup>64</sup> bytes/2<sup>64</sup> inodes.
- QFMT_VFS_V1,
- }
-}
-
-libc_bitflags!(
- /// Indicates the quota fields that are valid to read from.
- #[derive(Default)]
- pub struct QuotaValidFlags: u32 {
- /// The block hard & soft limit fields.
- QIF_BLIMITS;
- /// The current space field.
- QIF_SPACE;
- /// The inode hard & soft limit fields.
- QIF_ILIMITS;
- /// The current inodes field.
- QIF_INODES;
- /// The disk use time limit field.
- QIF_BTIME;
- /// The file quote time limit field.
- QIF_ITIME;
- /// All block & inode limits.
- QIF_LIMITS;
- /// The space & inodes usage fields.
- QIF_USAGE;
- /// The time limit fields.
- QIF_TIMES;
- /// All fields.
- QIF_ALL;
- }
-);
-
-/// Wrapper type for `if_dqblk`
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct Dqblk(libc::dqblk);
-
-impl Default for Dqblk {
- fn default() -> Dqblk {
- Dqblk(libc::dqblk {
- dqb_bhardlimit: 0,
- dqb_bsoftlimit: 0,
- dqb_curspace: 0,
- dqb_ihardlimit: 0,
- dqb_isoftlimit: 0,
- dqb_curinodes: 0,
- dqb_btime: 0,
- dqb_itime: 0,
- dqb_valid: 0,
- })
- }
-}
-
-impl Dqblk {
- /// The absolute limit on disk quota blocks allocated.
- pub fn blocks_hard_limit(&self) -> Option<u64> {
- let valid_fields =
- QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
- Some(self.0.dqb_bhardlimit)
- } else {
- None
- }
- }
-
- /// Set the absolute limit on disk quota blocks allocated.
- pub fn set_blocks_hard_limit(&mut self, limit: u64) {
- self.0.dqb_bhardlimit = limit;
- }
-
- /// Preferred limit on disk quota blocks
- pub fn blocks_soft_limit(&self) -> Option<u64> {
- let valid_fields =
- QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
- Some(self.0.dqb_bsoftlimit)
- } else {
- None
- }
- }
-
- /// Set the preferred limit on disk quota blocks allocated.
- pub fn set_blocks_soft_limit(&mut self, limit: u64) {
- self.0.dqb_bsoftlimit = limit;
- }
-
- /// Current occupied space (bytes).
- pub fn occupied_space(&self) -> Option<u64> {
- let valid_fields =
- QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_SPACE) {
- Some(self.0.dqb_curspace)
- } else {
- None
- }
- }
-
- /// Maximum number of allocated inodes.
- pub fn inodes_hard_limit(&self) -> Option<u64> {
- let valid_fields =
- QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
- Some(self.0.dqb_ihardlimit)
- } else {
- None
- }
- }
-
- /// Set the maximum number of allocated inodes.
- pub fn set_inodes_hard_limit(&mut self, limit: u64) {
- self.0.dqb_ihardlimit = limit;
- }
-
- /// Preferred inode limit
- pub fn inodes_soft_limit(&self) -> Option<u64> {
- let valid_fields =
- QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
- Some(self.0.dqb_isoftlimit)
- } else {
- None
- }
- }
-
- /// Set the preferred limit of allocated inodes.
- pub fn set_inodes_soft_limit(&mut self, limit: u64) {
- self.0.dqb_isoftlimit = limit;
- }
-
- /// Current number of allocated inodes.
- pub fn allocated_inodes(&self) -> Option<u64> {
- let valid_fields =
- QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_INODES) {
- Some(self.0.dqb_curinodes)
- } else {
- None
- }
- }
-
- /// Time limit for excessive disk use.
- pub fn block_time_limit(&self) -> Option<u64> {
- let valid_fields =
- QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_BTIME) {
- Some(self.0.dqb_btime)
- } else {
- None
- }
- }
-
- /// Set the time limit for excessive disk use.
- pub fn set_block_time_limit(&mut self, limit: u64) {
- self.0.dqb_btime = limit;
- }
-
- /// Time limit for excessive files.
- pub fn inode_time_limit(&self) -> Option<u64> {
- let valid_fields =
- QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
- if valid_fields.contains(QuotaValidFlags::QIF_ITIME) {
- Some(self.0.dqb_itime)
- } else {
- None
- }
- }
-
- /// Set the time limit for excessive files.
- pub fn set_inode_time_limit(&mut self, limit: u64) {
- self.0.dqb_itime = limit;
- }
-}
-
-fn quotactl<P: ?Sized + NixPath>(
- cmd: QuotaCmd,
- special: Option<&P>,
- id: c_int,
- addr: *mut c_char,
-) -> Result<()> {
- unsafe {
- Errno::clear();
- let res = match special {
- Some(dev) => dev.with_nix_path(|path| {
- libc::quotactl(cmd.as_int(), path.as_ptr(), id, addr)
- }),
- None => Ok(libc::quotactl(cmd.as_int(), ptr::null(), id, addr)),
- }?;
-
- Errno::result(res).map(drop)
- }
-}
-
-/// Turn on disk quotas for a block device.
-pub fn quotactl_on<P: ?Sized + NixPath>(
- which: QuotaType,
- special: &P,
- format: QuotaFmt,
- quota_file: &P,
-) -> Result<()> {
- quota_file.with_nix_path(|path| {
- let mut path_copy = path.to_bytes_with_nul().to_owned();
- let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char;
- quotactl(
- QuotaCmd(QuotaSubCmd::Q_QUOTAON, which),
- Some(special),
- format as c_int,
- p,
- )
- })?
-}
-
-/// Disable disk quotas for a block device.
-pub fn quotactl_off<P: ?Sized + NixPath>(
- which: QuotaType,
- special: &P,
-) -> Result<()> {
- quotactl(
- QuotaCmd(QuotaSubCmd::Q_QUOTAOFF, which),
- Some(special),
- 0,
- ptr::null_mut(),
- )
-}
-
-/// Update the on-disk copy of quota usages for a filesystem.
-///
-/// If `special` is `None`, then all file systems with active quotas are sync'd.
-pub fn quotactl_sync<P: ?Sized + NixPath>(
- which: QuotaType,
- special: Option<&P>,
-) -> Result<()> {
- quotactl(
- QuotaCmd(QuotaSubCmd::Q_SYNC, which),
- special,
- 0,
- ptr::null_mut(),
- )
-}
-
-/// Get disk quota limits and current usage for the given user/group id.
-pub fn quotactl_get<P: ?Sized + NixPath>(
- which: QuotaType,
- special: &P,
- id: c_int,
-) -> Result<Dqblk> {
- let mut dqblk = mem::MaybeUninit::uninit();
- quotactl(
- QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which),
- Some(special),
- id,
- dqblk.as_mut_ptr() as *mut c_char,
- )?;
- Ok(unsafe { Dqblk(dqblk.assume_init()) })
-}
-
-/// Configure quota values for the specified fields for a given user/group id.
-pub fn quotactl_set<P: ?Sized + NixPath>(
- which: QuotaType,
- special: &P,
- id: c_int,
- dqblk: &Dqblk,
- fields: QuotaValidFlags,
-) -> Result<()> {
- let mut dqblk_copy = *dqblk;
- dqblk_copy.0.dqb_valid = fields.bits();
- quotactl(
- QuotaCmd(QuotaSubCmd::Q_SETQUOTA, which),
- Some(special),
- id,
- &mut dqblk_copy as *mut _ as *mut c_char,
- )
-}
diff --git a/vendor/nix/src/sys/reboot.rs b/vendor/nix/src/sys/reboot.rs
deleted file mode 100644
index 02d98162b..000000000
--- a/vendor/nix/src/sys/reboot.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
-
-use crate::errno::Errno;
-use crate::Result;
-use std::convert::Infallible;
-use std::mem::drop;
-
-libc_enum! {
- /// How exactly should the system be rebooted.
- ///
- /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
- /// enabling/disabling Ctrl-Alt-Delete.
- #[repr(i32)]
- #[non_exhaustive]
- pub enum RebootMode {
- /// Halt the system.
- RB_HALT_SYSTEM,
- /// Execute a kernel that has been loaded earlier with
- /// [`kexec_load(2)`](https://man7.org/linux/man-pages/man2/kexec_load.2.html).
- RB_KEXEC,
- /// Stop the system and switch off power, if possible.
- RB_POWER_OFF,
- /// Restart the system.
- RB_AUTOBOOT,
- // we do not support Restart2.
- /// Suspend the system using software suspend.
- RB_SW_SUSPEND,
- }
-}
-
-/// Reboots or shuts down the system.
-pub fn reboot(how: RebootMode) -> Result<Infallible> {
- unsafe { libc::reboot(how as libc::c_int) };
- Err(Errno::last())
-}
-
-/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
-///
-/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
-pub fn set_cad_enabled(enable: bool) -> Result<()> {
- let cmd = if enable {
- libc::RB_ENABLE_CAD
- } else {
- libc::RB_DISABLE_CAD
- };
- let res = unsafe { libc::reboot(cmd) };
- Errno::result(res).map(drop)
-}
diff --git a/vendor/nix/src/sys/resource.rs b/vendor/nix/src/sys/resource.rs
deleted file mode 100644
index 892773776..000000000
--- a/vendor/nix/src/sys/resource.rs
+++ /dev/null
@@ -1,443 +0,0 @@
-//! Configure the process resource limits.
-use cfg_if::cfg_if;
-use libc::{c_int, c_long, rusage};
-
-use crate::errno::Errno;
-use crate::sys::time::TimeVal;
-use crate::Result;
-pub use libc::rlim_t;
-pub use libc::RLIM_INFINITY;
-use std::mem;
-
-cfg_if! {
- if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
- use libc::{__rlimit_resource_t, rlimit};
- } else if #[cfg(any(
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "macos",
- target_os = "ios",
- target_os = "android",
- target_os = "dragonfly",
- all(target_os = "linux", not(target_env = "gnu"))
- ))]{
- use libc::rlimit;
- }
-}
-
-libc_enum! {
- /// Types of process resources.
- ///
- /// The Resource enum is platform dependent. Check different platform
- /// manuals for more details. Some platform links have been provided for
- /// easier reference (non-exhaustive).
- ///
- /// * [Linux](https://man7.org/linux/man-pages/man2/getrlimit.2.html)
- /// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=setrlimit)
- /// * [NetBSD](https://man.netbsd.org/setrlimit.2)
-
- // linux-gnu uses u_int as resource enum, which is implemented in libc as
- // well.
- //
- // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html
- // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs
- #[cfg_attr(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), repr(u32))]
- #[cfg_attr(any(
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "macos",
- target_os = "ios",
- target_os = "android",
- target_os = "dragonfly",
- all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc")))
- ), repr(i32))]
- #[non_exhaustive]
- pub enum Resource {
- #[cfg(not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// The maximum amount (in bytes) of virtual memory the process is
- /// allowed to map.
- RLIMIT_AS,
- /// The largest size (in bytes) core(5) file that may be created.
- RLIMIT_CORE,
- /// The maximum amount of cpu time (in seconds) to be used by each
- /// process.
- RLIMIT_CPU,
- /// The maximum size (in bytes) of the data segment for a process
- RLIMIT_DATA,
- /// The largest size (in bytes) file that may be created.
- RLIMIT_FSIZE,
- /// The maximum number of open files for this process.
- RLIMIT_NOFILE,
- /// The maximum size (in bytes) of the stack segment for a process.
- RLIMIT_STACK,
-
- #[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// The maximum number of kqueues this user id is allowed to create.
- RLIMIT_KQUEUES,
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// A limit on the combined number of flock locks and fcntl leases that
- /// this process may establish.
- RLIMIT_LOCKS,
-
- #[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "linux",
- target_os = "netbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// The maximum size (in bytes) which a process may lock into memory
- /// using the mlock(2) system call.
- RLIMIT_MEMLOCK,
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// A limit on the number of bytes that can be allocated for POSIX
- /// message queues for the real user ID of the calling process.
- RLIMIT_MSGQUEUE,
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// A ceiling to which the process's nice value can be raised using
- /// setpriority or nice.
- RLIMIT_NICE,
-
- #[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// The maximum number of simultaneous processes for this user id.
- RLIMIT_NPROC,
-
- #[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// The maximum number of pseudo-terminals this user id is allowed to
- /// create.
- RLIMIT_NPTS,
-
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// When there is memory pressure and swap is available, prioritize
- /// eviction of a process' resident pages beyond this amount (in bytes).
- RLIMIT_RSS,
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// A ceiling on the real-time priority that may be set for this process
- /// using sched_setscheduler and sched_set‐ param.
- RLIMIT_RTPRIO,
-
- #[cfg(any(target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// A limit (in microseconds) on the amount of CPU time that a process
- /// scheduled under a real-time scheduling policy may con‐ sume without
- /// making a blocking system call.
- RLIMIT_RTTIME,
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// A limit on the number of signals that may be queued for the real
- /// user ID of the calling process.
- RLIMIT_SIGPENDING,
-
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// The maximum size (in bytes) of socket buffer usage for this user.
- RLIMIT_SBSIZE,
-
- #[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// The maximum size (in bytes) of the swap space that may be reserved
- /// or used by all of this user id's processes.
- RLIMIT_SWAP,
-
- #[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// An alias for RLIMIT_AS.
- RLIMIT_VMEM,
- }
-}
-
-/// Get the current processes resource limits
-///
-/// The special value [`RLIM_INFINITY`] indicates that no limit will be
-/// enforced.
-///
-/// # Parameters
-///
-/// * `resource`: The [`Resource`] that we want to get the limits of.
-///
-/// # Examples
-///
-/// ```
-/// # use nix::sys::resource::{getrlimit, Resource};
-///
-/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
-/// println!("current soft_limit: {}", soft_limit);
-/// println!("current hard_limit: {}", hard_limit);
-/// ```
-///
-/// # References
-///
-/// [getrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
-///
-/// [`Resource`]: enum.Resource.html
-pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> {
- let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();
-
- cfg_if! {
- if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
- let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
- } else {
- let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
- }
- }
-
- Errno::result(res).map(|_| {
- let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() };
- (rlim_cur, rlim_max)
- })
-}
-
-/// Set the current processes resource limits
-///
-/// # Parameters
-///
-/// * `resource`: The [`Resource`] that we want to set the limits of.
-/// * `soft_limit`: The value that the kernel enforces for the corresponding
-/// resource.
-/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to
-/// the current hard limit for non-root users.
-///
-/// The special value [`RLIM_INFINITY`] indicates that no limit will be
-/// enforced.
-///
-/// # Examples
-///
-/// ```
-/// # use nix::sys::resource::{setrlimit, Resource};
-///
-/// let soft_limit = 512;
-/// let hard_limit = 1024;
-/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
-/// ```
-///
-/// # References
-///
-/// [setrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
-///
-/// [`Resource`]: enum.Resource.html
-///
-/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`.
-pub fn setrlimit(
- resource: Resource,
- soft_limit: rlim_t,
- hard_limit: rlim_t,
-) -> Result<()> {
- let new_rlim = rlimit {
- rlim_cur: soft_limit,
- rlim_max: hard_limit,
- };
- cfg_if! {
- if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
- let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
- }else{
- let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
- }
- }
-
- Errno::result(res).map(drop)
-}
-
-libc_enum! {
- /// Whose resource usage should be returned by [`getrusage`].
- #[repr(i32)]
- #[non_exhaustive]
- pub enum UsageWho {
- /// Resource usage for the current process.
- RUSAGE_SELF,
-
- /// Resource usage for all the children that have terminated and been waited for.
- RUSAGE_CHILDREN,
-
- #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// Resource usage for the calling thread.
- RUSAGE_THREAD,
- }
-}
-
-/// Output of `getrusage` with information about resource usage. Some of the fields
-/// may be unused in some platforms, and will be always zeroed out. See their manuals
-/// for details.
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct Usage(rusage);
-
-impl AsRef<rusage> for Usage {
- fn as_ref(&self) -> &rusage {
- &self.0
- }
-}
-
-impl AsMut<rusage> for Usage {
- fn as_mut(&mut self) -> &mut rusage {
- &mut self.0
- }
-}
-
-impl Usage {
- /// Total amount of time spent executing in user mode.
- pub fn user_time(&self) -> TimeVal {
- TimeVal::from(self.0.ru_utime)
- }
-
- /// Total amount of time spent executing in kernel mode.
- pub fn system_time(&self) -> TimeVal {
- TimeVal::from(self.0.ru_stime)
- }
-
- /// The resident set size at its peak, in kilobytes.
- pub fn max_rss(&self) -> c_long {
- self.0.ru_maxrss
- }
-
- /// Integral value expressed in kilobytes times ticks of execution indicating
- /// the amount of text memory shared with other processes.
- pub fn shared_integral(&self) -> c_long {
- self.0.ru_ixrss
- }
-
- /// Integral value expressed in kilobytes times ticks of execution indicating
- /// the amount of unshared memory used by data.
- pub fn unshared_data_integral(&self) -> c_long {
- self.0.ru_idrss
- }
-
- /// Integral value expressed in kilobytes times ticks of execution indicating
- /// the amount of unshared memory used for stack space.
- pub fn unshared_stack_integral(&self) -> c_long {
- self.0.ru_isrss
- }
-
- /// Number of page faults that were served without resorting to I/O, with pages
- /// that have been allocated previously by the kernel.
- pub fn minor_page_faults(&self) -> c_long {
- self.0.ru_minflt
- }
-
- /// Number of page faults that were served through I/O (i.e. swap).
- pub fn major_page_faults(&self) -> c_long {
- self.0.ru_majflt
- }
-
- /// Number of times all of the memory was fully swapped out.
- pub fn full_swaps(&self) -> c_long {
- self.0.ru_nswap
- }
-
- /// Number of times a read was done from a block device.
- pub fn block_reads(&self) -> c_long {
- self.0.ru_inblock
- }
-
- /// Number of times a write was done to a block device.
- pub fn block_writes(&self) -> c_long {
- self.0.ru_oublock
- }
-
- /// Number of IPC messages sent.
- pub fn ipc_sends(&self) -> c_long {
- self.0.ru_msgsnd
- }
-
- /// Number of IPC messages received.
- pub fn ipc_receives(&self) -> c_long {
- self.0.ru_msgrcv
- }
-
- /// Number of signals received.
- pub fn signals(&self) -> c_long {
- self.0.ru_nsignals
- }
-
- /// Number of times a context switch was voluntarily invoked.
- pub fn voluntary_context_switches(&self) -> c_long {
- self.0.ru_nvcsw
- }
-
- /// Number of times a context switch was imposed by the kernel (usually due to
- /// time slice expiring or preemption by a higher priority process).
- pub fn involuntary_context_switches(&self) -> c_long {
- self.0.ru_nivcsw
- }
-}
-
-/// Get usage information for a process, its children or the current thread
-///
-/// Real time information can be obtained for either the current process or (in some
-/// systems) thread, but information about children processes is only provided for
-/// those that have terminated and been waited for (see [`super::wait::wait`]).
-///
-/// Some information may be missing depending on the platform, and the way information
-/// is provided for children may also vary. Check the manuals for details.
-///
-/// # References
-///
-/// * [getrusage(2)](https://pubs.opengroup.org/onlinepubs/009696699/functions/getrusage.html)
-/// * [Linux](https://man7.org/linux/man-pages/man2/getrusage.2.html)
-/// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=getrusage)
-/// * [NetBSD](https://man.netbsd.org/getrusage.2)
-/// * [MacOS](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getrusage.2.html)
-///
-/// [`UsageWho`]: enum.UsageWho.html
-///
-/// Note: `getrusage` provides a safe wrapper to libc's [`libc::getrusage`].
-pub fn getrusage(who: UsageWho) -> Result<Usage> {
- unsafe {
- let mut rusage = mem::MaybeUninit::<rusage>::uninit();
- let res = libc::getrusage(who as c_int, rusage.as_mut_ptr());
- Errno::result(res).map(|_| Usage(rusage.assume_init()))
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::{getrusage, UsageWho};
-
- #[test]
- pub fn test_self_cpu_time() {
- // Make sure some CPU time is used.
- let mut numbers: Vec<i32> = (1..1_000_000).collect();
- numbers.iter_mut().for_each(|item| *item *= 2);
-
- // FIXME: this is here to help ensure the compiler does not optimize the whole
- // thing away. Replace the assert with test::black_box once stabilized.
- assert_eq!(numbers[100..200].iter().sum::<i32>(), 30_100);
-
- let usage = getrusage(UsageWho::RUSAGE_SELF)
- .expect("Failed to call getrusage for SELF");
- let rusage = usage.as_ref();
-
- let user = usage.user_time();
- assert!(user.tv_sec() > 0 || user.tv_usec() > 0);
- assert_eq!(user.tv_sec(), rusage.ru_utime.tv_sec);
- assert_eq!(user.tv_usec(), rusage.ru_utime.tv_usec);
- }
-}
diff --git a/vendor/nix/src/sys/select.rs b/vendor/nix/src/sys/select.rs
deleted file mode 100644
index 7a94cff87..000000000
--- a/vendor/nix/src/sys/select.rs
+++ /dev/null
@@ -1,455 +0,0 @@
-//! Portably monitor a group of file descriptors for readiness.
-use crate::errno::Errno;
-use crate::sys::time::{TimeSpec, TimeVal};
-use crate::Result;
-use libc::{self, c_int};
-use std::convert::TryFrom;
-use std::iter::FusedIterator;
-use std::mem;
-use std::ops::Range;
-use std::os::unix::io::RawFd;
-use std::ptr::{null, null_mut};
-
-pub use libc::FD_SETSIZE;
-
-/// Contains a set of file descriptors used by [`select`]
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct FdSet(libc::fd_set);
-
-fn assert_fd_valid(fd: RawFd) {
- assert!(
- usize::try_from(fd).map_or(false, |fd| fd < FD_SETSIZE),
- "fd must be in the range 0..FD_SETSIZE",
- );
-}
-
-impl FdSet {
- /// Create an empty `FdSet`
- pub fn new() -> FdSet {
- let mut fdset = mem::MaybeUninit::uninit();
- unsafe {
- libc::FD_ZERO(fdset.as_mut_ptr());
- FdSet(fdset.assume_init())
- }
- }
-
- /// Add a file descriptor to an `FdSet`
- pub fn insert(&mut self, fd: RawFd) {
- assert_fd_valid(fd);
- unsafe { libc::FD_SET(fd, &mut self.0) };
- }
-
- /// Remove a file descriptor from an `FdSet`
- pub fn remove(&mut self, fd: RawFd) {
- assert_fd_valid(fd);
- unsafe { libc::FD_CLR(fd, &mut self.0) };
- }
-
- /// Test an `FdSet` for the presence of a certain file descriptor.
- pub fn contains(&self, fd: RawFd) -> bool {
- assert_fd_valid(fd);
- unsafe { libc::FD_ISSET(fd, &self.0) }
- }
-
- /// Remove all file descriptors from this `FdSet`.
- pub fn clear(&mut self) {
- unsafe { libc::FD_ZERO(&mut self.0) };
- }
-
- /// Finds the highest file descriptor in the set.
- ///
- /// Returns `None` if the set is empty.
- ///
- /// This can be used to calculate the `nfds` parameter of the [`select`] function.
- ///
- /// # Example
- ///
- /// ```
- /// # use nix::sys::select::FdSet;
- /// let mut set = FdSet::new();
- /// set.insert(4);
- /// set.insert(9);
- /// assert_eq!(set.highest(), Some(9));
- /// ```
- ///
- /// [`select`]: fn.select.html
- pub fn highest(&self) -> Option<RawFd> {
- self.fds(None).next_back()
- }
-
- /// 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.
- ///
- /// # Examples
- ///
- /// ```
- /// # use nix::sys::select::FdSet;
- /// # use std::os::unix::io::RawFd;
- /// let mut set = FdSet::new();
- /// set.insert(4);
- /// set.insert(9);
- /// let fds: Vec<RawFd> = set.fds(None).collect();
- /// assert_eq!(fds, vec![4, 9]);
- /// ```
- #[inline]
- pub fn fds(&self, highest: Option<RawFd>) -> Fds {
- Fds {
- set: self,
- range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE),
- }
- }
-}
-
-impl Default for FdSet {
- fn default() -> Self {
- Self::new()
- }
-}
-
-/// Iterator over `FdSet`.
-#[derive(Debug)]
-pub struct Fds<'a> {
- set: &'a FdSet,
- range: Range<usize>,
-}
-
-impl<'a> Iterator for Fds<'a> {
- type Item = RawFd;
-
- fn next(&mut self) -> Option<RawFd> {
- for i in &mut self.range {
- if self.set.contains(i as RawFd) {
- return Some(i as RawFd);
- }
- }
- None
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let (_, upper) = self.range.size_hint();
- (0, upper)
- }
-}
-
-impl<'a> DoubleEndedIterator for Fds<'a> {
- #[inline]
- fn next_back(&mut self) -> Option<RawFd> {
- while let Some(i) = self.range.next_back() {
- if self.set.contains(i as RawFd) {
- return Some(i as RawFd);
- }
- }
- None
- }
-}
-
-impl<'a> FusedIterator for Fds<'a> {}
-
-/// Monitors file descriptors for readiness
-///
-/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
-/// file descriptors that are ready for the given operation are set.
-///
-/// When this function returns, `timeout` has an implementation-defined value.
-///
-/// # Parameters
-///
-/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this
-/// is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1
-/// to the maximum of that.
-/// * `readfds`: File descriptors to check for being ready to read.
-/// * `writefds`: File descriptors to check for being ready to write.
-/// * `errorfds`: File descriptors to check for pending error conditions.
-/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block
-/// indefinitely).
-///
-/// # References
-///
-/// [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,
- readfds: R,
- writefds: W,
- errorfds: E,
- timeout: T,
-) -> Result<c_int>
-where
- N: Into<Option<c_int>>,
- R: Into<Option<&'a mut FdSet>>,
- W: Into<Option<&'a mut FdSet>>,
- E: Into<Option<&'a mut FdSet>>,
- T: Into<Option<&'a mut TimeVal>>,
-{
- let mut readfds = readfds.into();
- let mut writefds = writefds.into();
- let mut errorfds = errorfds.into();
- let timeout = timeout.into();
-
- let nfds = nfds.into().unwrap_or_else(|| {
- readfds
- .iter_mut()
- .chain(writefds.iter_mut())
- .chain(errorfds.iter_mut())
- .map(|set| set.highest().unwrap_or(-1))
- .max()
- .unwrap_or(-1)
- + 1
- });
-
- let readfds = readfds
- .map(|set| set as *mut _ as *mut libc::fd_set)
- .unwrap_or(null_mut());
- let writefds = writefds
- .map(|set| set as *mut _ as *mut libc::fd_set)
- .unwrap_or(null_mut());
- let errorfds = errorfds
- .map(|set| set as *mut _ as *mut libc::fd_set)
- .unwrap_or(null_mut());
- let timeout = timeout
- .map(|tv| tv as *mut _ as *mut libc::timeval)
- .unwrap_or(null_mut());
-
- let res =
- unsafe { libc::select(nfds, readfds, writefds, errorfds, timeout) };
-
- Errno::result(res)
-}
-
-feature! {
-#![feature = "signal"]
-
-use crate::sys::signal::SigSet;
-
-/// Monitors file descriptors for readiness with an altered signal mask.
-///
-/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
-/// file descriptors that are ready for the given operation are set.
-///
-/// When this function returns, the original signal mask is restored.
-///
-/// Unlike [`select`](#fn.select), `pselect` does not mutate the `timeout` value.
-///
-/// # Parameters
-///
-/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this
-/// is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1
-/// to the maximum of that.
-/// * `readfds`: File descriptors to check for read readiness
-/// * `writefds`: File descriptors to check for write readiness
-/// * `errorfds`: File descriptors to check for pending error conditions.
-/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block
-/// indefinitely).
-/// * `sigmask`: Signal mask to activate while waiting for file descriptors to turn
-/// ready (`None` to set no alternative signal mask).
-///
-/// # References
-///
-/// [pselect(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html)
-///
-/// [The new pselect() system call](https://lwn.net/Articles/176911/)
-///
-/// [`FdSet::highest`]: struct.FdSet.html#method.highest
-pub fn pselect<'a, N, R, W, E, T, S>(nfds: N,
- readfds: R,
- writefds: W,
- errorfds: E,
- timeout: T,
- sigmask: S) -> Result<c_int>
-where
- N: Into<Option<c_int>>,
- R: Into<Option<&'a mut FdSet>>,
- W: Into<Option<&'a mut FdSet>>,
- E: Into<Option<&'a mut FdSet>>,
- T: Into<Option<&'a TimeSpec>>,
- S: Into<Option<&'a SigSet>>,
-{
- let mut readfds = readfds.into();
- let mut writefds = writefds.into();
- let mut errorfds = errorfds.into();
- let sigmask = sigmask.into();
- let timeout = timeout.into();
-
- let nfds = nfds.into().unwrap_or_else(|| {
- readfds.iter_mut()
- .chain(writefds.iter_mut())
- .chain(errorfds.iter_mut())
- .map(|set| set.highest().unwrap_or(-1))
- .max()
- .unwrap_or(-1) + 1
- });
-
- let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
- let timeout = timeout.map(|ts| ts.as_ref() as *const libc::timespec).unwrap_or(null());
- let sigmask = sigmask.map(|sm| sm.as_ref() as *const libc::sigset_t).unwrap_or(null());
-
- let res = unsafe {
- libc::pselect(nfds, readfds, writefds, errorfds, timeout, sigmask)
- };
-
- Errno::result(res)
-}
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::sys::time::{TimeVal, TimeValLike};
- use crate::unistd::{pipe, write};
- use std::os::unix::io::RawFd;
-
- #[test]
- fn fdset_insert() {
- let mut fd_set = FdSet::new();
-
- for i in 0..FD_SETSIZE {
- assert!(!fd_set.contains(i as RawFd));
- }
-
- fd_set.insert(7);
-
- assert!(fd_set.contains(7));
- }
-
- #[test]
- fn fdset_remove() {
- let mut fd_set = FdSet::new();
-
- for i in 0..FD_SETSIZE {
- assert!(!fd_set.contains(i as RawFd));
- }
-
- fd_set.insert(7);
- fd_set.remove(7);
-
- for i in 0..FD_SETSIZE {
- assert!(!fd_set.contains(i as RawFd));
- }
- }
-
- #[test]
- fn fdset_clear() {
- let mut fd_set = FdSet::new();
- fd_set.insert(1);
- fd_set.insert((FD_SETSIZE / 2) as RawFd);
- fd_set.insert((FD_SETSIZE - 1) as RawFd);
-
- fd_set.clear();
-
- for i in 0..FD_SETSIZE {
- assert!(!fd_set.contains(i as RawFd));
- }
- }
-
- #[test]
- fn fdset_highest() {
- let mut set = FdSet::new();
- assert_eq!(set.highest(), None);
- set.insert(0);
- assert_eq!(set.highest(), Some(0));
- set.insert(90);
- assert_eq!(set.highest(), Some(90));
- set.remove(0);
- assert_eq!(set.highest(), Some(90));
- set.remove(90);
- assert_eq!(set.highest(), None);
-
- set.insert(4);
- set.insert(5);
- set.insert(7);
- assert_eq!(set.highest(), Some(7));
- }
-
- #[test]
- fn fdset_fds() {
- let mut set = FdSet::new();
- assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![]);
- set.insert(0);
- assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0]);
- set.insert(90);
- assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0, 90]);
-
- // highest limit
- assert_eq!(set.fds(Some(89)).collect::<Vec<_>>(), vec![0]);
- assert_eq!(set.fds(Some(90)).collect::<Vec<_>>(), vec![0, 90]);
- }
-
- #[test]
- fn test_select() {
- let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let (r2, _w2) = pipe().unwrap();
-
- let mut fd_set = FdSet::new();
- fd_set.insert(r1);
- fd_set.insert(r2);
-
- let mut timeout = TimeVal::seconds(10);
- assert_eq!(
- 1,
- select(None, &mut fd_set, None, None, &mut timeout).unwrap()
- );
- assert!(fd_set.contains(r1));
- assert!(!fd_set.contains(r2));
- }
-
- #[test]
- fn test_select_nfds() {
- let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let (r2, _w2) = pipe().unwrap();
-
- let mut fd_set = FdSet::new();
- fd_set.insert(r1);
- fd_set.insert(r2);
-
- let mut timeout = TimeVal::seconds(10);
- assert_eq!(
- 1,
- select(
- Some(fd_set.highest().unwrap() + 1),
- &mut fd_set,
- None,
- None,
- &mut timeout
- )
- .unwrap()
- );
- assert!(fd_set.contains(r1));
- assert!(!fd_set.contains(r2));
- }
-
- #[test]
- fn test_select_nfds2() {
- let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let (r2, _w2) = pipe().unwrap();
-
- let mut fd_set = FdSet::new();
- fd_set.insert(r1);
- fd_set.insert(r2);
-
- let mut timeout = TimeVal::seconds(10);
- assert_eq!(
- 1,
- select(
- ::std::cmp::max(r1, r2) + 1,
- &mut fd_set,
- None,
- None,
- &mut timeout
- )
- .unwrap()
- );
- assert!(fd_set.contains(r1));
- assert!(!fd_set.contains(r2));
- }
-}
diff --git a/vendor/nix/src/sys/sendfile.rs b/vendor/nix/src/sys/sendfile.rs
deleted file mode 100644
index fb293a4e7..000000000
--- a/vendor/nix/src/sys/sendfile.rs
+++ /dev/null
@@ -1,277 +0,0 @@
-//! Send data from a file to a socket, bypassing userland.
-
-use cfg_if::cfg_if;
-use std::os::unix::io::RawFd;
-use std::ptr;
-
-use libc::{self, off_t};
-
-use crate::errno::Errno;
-use crate::Result;
-
-/// 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(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn sendfile(
- out_fd: RawFd,
- in_fd: RawFd,
- offset: Option<&mut off_t>,
- count: usize,
-) -> Result<usize> {
- let offset = offset
- .map(|offset| offset as *mut _)
- .unwrap_or(ptr::null_mut());
- let ret = unsafe { libc::sendfile(out_fd, in_fd, offset, count) };
- 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")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-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 = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos"))] {
- use std::io::IoSlice;
-
- #[derive(Clone, Debug)]
- struct SendfileHeaderTrailer<'a>(
- libc::sf_hdtr,
- Option<Vec<IoSlice<'a>>>,
- Option<Vec<IoSlice<'a>>>,
- );
-
- impl<'a> SendfileHeaderTrailer<'a> {
- fn new(
- headers: Option<&'a [&'a [u8]]>,
- trailers: Option<&'a [&'a [u8]]>
- ) -> SendfileHeaderTrailer<'a> {
- 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: {
- header_iovecs
- .as_ref()
- .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
- },
- hdr_cnt: header_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32,
- trailers: {
- trailer_iovecs
- .as_ref()
- .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
- },
- trl_cnt: trailer_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32
- },
- header_iovecs,
- trailer_iovecs,
- )
- }
- }
- }
-}
-
-cfg_if! {
- if #[cfg(target_os = "freebsd")] {
- use libc::c_int;
-
- libc_bitflags!{
- /// Configuration options for [`sendfile`.](fn.sendfile.html)
- pub struct SfFlags: c_int {
- /// Causes `sendfile` to return EBUSY instead of blocking when attempting to read a
- /// busy page.
- SF_NODISKIO;
- /// Causes `sendfile` to sleep until the network stack releases its reference to the
- /// VM pages read. When `sendfile` returns, the data is not guaranteed to have been
- /// sent, but it is safe to modify the file.
- SF_SYNC;
- /// Causes `sendfile` to cache exactly the number of pages specified in the
- /// `readahead` parameter, disabling caching heuristics.
- SF_USER_READAHEAD;
- /// Causes `sendfile` not to cache the data read.
- SF_NOCACHE;
- }
- }
-
- /// Read up to `count` bytes from `in_fd` starting at `offset` and write to `out_sock`.
- ///
- /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if
- /// an error occurs.
- ///
- /// `in_fd` must describe a regular file or shared memory object. `out_sock` must describe a
- /// stream socket.
- ///
- /// If `offset` falls past the end of the file, the function returns success and zero bytes
- /// written.
- ///
- /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of
- /// file (EOF).
- ///
- /// `headers` and `trailers` specify optional slices of byte slices to be sent before and
- /// after the data read from `in_fd`, respectively. The length of headers and trailers sent
- /// is included in the returned count of bytes written. The values of `offset` and `count`
- /// do not apply to headers or trailers.
- ///
- /// `readahead` specifies the minimum number of pages to cache in memory ahead of the page
- /// currently being sent.
- ///
- /// For more information, see
- /// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2)
- #[allow(clippy::too_many_arguments)]
- pub fn sendfile(
- in_fd: RawFd,
- out_sock: RawFd,
- offset: off_t,
- count: Option<usize>,
- headers: Option<&[&[u8]]>,
- trailers: Option<&[&[u8]]>,
- flags: SfFlags,
- readahead: u16
- ) -> (Result<()>, off_t) {
- // Readahead goes in upper 16 bits
- // Flags goes in lower 16 bits
- // see `man 2 sendfile`
- let ra32 = u32::from(readahead);
- let flags: u32 = (ra32 << 16) | (flags.bits() as u32);
- let mut bytes_sent: off_t = 0;
- let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
- let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
- let return_code = unsafe {
- libc::sendfile(in_fd,
- out_sock,
- offset,
- count.unwrap_or(0),
- hdtr_ptr as *mut libc::sf_hdtr,
- &mut bytes_sent as *mut off_t,
- flags as c_int)
- };
- (Errno::result(return_code).and(Ok(())), bytes_sent)
- }
- } else if #[cfg(target_os = "dragonfly")] {
- /// Read up to `count` bytes from `in_fd` starting at `offset` and write to `out_sock`.
- ///
- /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if
- /// an error occurs.
- ///
- /// `in_fd` must describe a regular file. `out_sock` must describe a stream socket.
- ///
- /// If `offset` falls past the end of the file, the function returns success and zero bytes
- /// written.
- ///
- /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of
- /// file (EOF).
- ///
- /// `headers` and `trailers` specify optional slices of byte slices to be sent before and
- /// after the data read from `in_fd`, respectively. The length of headers and trailers sent
- /// is included in the returned count of bytes written. The values of `offset` and `count`
- /// do not apply to headers or trailers.
- ///
- /// For more information, see
- /// [the sendfile(2) man page.](https://leaf.dragonflybsd.org/cgi/web-man?command=sendfile&section=2)
- pub fn sendfile(
- in_fd: RawFd,
- out_sock: RawFd,
- offset: off_t,
- count: Option<usize>,
- headers: Option<&[&[u8]]>,
- trailers: Option<&[&[u8]]>,
- ) -> (Result<()>, off_t) {
- let mut bytes_sent: off_t = 0;
- let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
- let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
- let return_code = unsafe {
- libc::sendfile(in_fd,
- out_sock,
- offset,
- count.unwrap_or(0),
- hdtr_ptr as *mut libc::sf_hdtr,
- &mut bytes_sent as *mut off_t,
- 0)
- };
- (Errno::result(return_code).and(Ok(())), bytes_sent)
- }
- } else if #[cfg(any(target_os = "ios", target_os = "macos"))] {
- /// Read bytes from `in_fd` starting at `offset` and write up to `count` bytes to
- /// `out_sock`.
- ///
- /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if
- /// an error occurs.
- ///
- /// `in_fd` must describe a regular file. `out_sock` must describe a stream socket.
- ///
- /// If `offset` falls past the end of the file, the function returns success and zero bytes
- /// written.
- ///
- /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of
- /// file (EOF).
- ///
- /// `hdtr` specifies an optional list of headers and trailers to be sent before and after
- /// the data read from `in_fd`, respectively. The length of headers and trailers sent is
- /// included in the returned count of bytes written. If any headers are specified and
- /// `count` is non-zero, the length of the headers will be counted in the limit of total
- /// bytes sent. Trailers do not count toward the limit of bytes sent and will always be sent
- /// regardless. The value of `offset` does not affect headers or trailers.
- ///
- /// For more information, see
- /// [the sendfile(2) man page.](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/sendfile.2.html)
- pub fn sendfile(
- in_fd: RawFd,
- out_sock: RawFd,
- offset: off_t,
- count: Option<off_t>,
- headers: Option<&[&[u8]]>,
- trailers: Option<&[&[u8]]>
- ) -> (Result<()>, off_t) {
- let mut len = count.unwrap_or(0);
- let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
- let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
- let return_code = unsafe {
- libc::sendfile(in_fd,
- out_sock,
- offset,
- &mut len as *mut off_t,
- hdtr_ptr as *mut libc::sf_hdtr,
- 0)
- };
- (Errno::result(return_code).and(Ok(())), len)
- }
- }
-}
diff --git a/vendor/nix/src/sys/signal.rs b/vendor/nix/src/sys/signal.rs
deleted file mode 100644
index d3746e609..000000000
--- a/vendor/nix/src/sys/signal.rs
+++ /dev/null
@@ -1,1348 +0,0 @@
-// Portions of this file are Copyright 2014 The Rust Project Developers.
-// See https://www.rust-lang.org/policies/licenses.
-
-//! Operating system signals.
-
-use crate::errno::Errno;
-use crate::{Error, Result};
-use cfg_if::cfg_if;
-use std::fmt;
-use std::mem;
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-use std::os::unix::io::RawFd;
-use std::ptr;
-use std::str::FromStr;
-
-#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
-#[cfg(any(feature = "aio", feature = "signal"))]
-pub use self::sigevent::*;
-
-#[cfg(any(feature = "aio", feature = "process", feature = "signal"))]
-libc_enum! {
- /// Types of operating system signals
- // Currently there is only one definition of c_int in libc, as well as only one
- // type for signal constants.
- // We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
- // this is not (yet) possible.
- #[repr(i32)]
- #[non_exhaustive]
- #[cfg_attr(docsrs, doc(cfg(any(feature = "aio", feature = "signal"))))]
- pub enum Signal {
- /// Hangup
- SIGHUP,
- /// Interrupt
- SIGINT,
- /// Quit
- SIGQUIT,
- /// Illegal instruction (not reset when caught)
- SIGILL,
- /// Trace trap (not reset when caught)
- SIGTRAP,
- /// Abort
- SIGABRT,
- /// Bus error
- SIGBUS,
- /// Floating point exception
- SIGFPE,
- /// Kill (cannot be caught or ignored)
- SIGKILL,
- /// User defined signal 1
- SIGUSR1,
- /// Segmentation violation
- SIGSEGV,
- /// User defined signal 2
- SIGUSR2,
- /// Write on a pipe with no one to read it
- SIGPIPE,
- /// Alarm clock
- SIGALRM,
- /// Software termination signal from kill
- SIGTERM,
- /// Stack fault (obsolete)
- #[cfg(all(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"),
- not(any(target_arch = "mips", target_arch = "mips64",
- target_arch = "sparc64"))))]
- SIGSTKFLT,
- /// To parent on child stop or exit
- SIGCHLD,
- /// Continue a stopped process
- SIGCONT,
- /// Sendable stop signal not from tty
- SIGSTOP,
- /// Stop signal from tty
- SIGTSTP,
- /// To readers pgrp upon background tty read
- SIGTTIN,
- /// Like TTIN if (tp->t_local&LTOSTOP)
- SIGTTOU,
- /// Urgent condition on IO channel
- SIGURG,
- /// Exceeded CPU time limit
- SIGXCPU,
- /// Exceeded file size limit
- SIGXFSZ,
- /// Virtual time alarm
- SIGVTALRM,
- /// Profiling time alarm
- SIGPROF,
- /// Window size changes
- SIGWINCH,
- /// Input/output possible signal
- #[cfg(not(target_os = "haiku"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- SIGIO,
- #[cfg(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// Power failure imminent.
- SIGPWR,
- /// Bad system call
- SIGSYS,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// Emulator trap
- SIGEMT,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- /// Information request
- SIGINFO,
- }
- impl TryFrom<i32>
-}
-
-#[cfg(feature = "signal")]
-impl FromStr for Signal {
- type Err = Error;
- fn from_str(s: &str) -> Result<Signal> {
- Ok(match s {
- "SIGHUP" => Signal::SIGHUP,
- "SIGINT" => Signal::SIGINT,
- "SIGQUIT" => Signal::SIGQUIT,
- "SIGILL" => Signal::SIGILL,
- "SIGTRAP" => Signal::SIGTRAP,
- "SIGABRT" => Signal::SIGABRT,
- "SIGBUS" => Signal::SIGBUS,
- "SIGFPE" => Signal::SIGFPE,
- "SIGKILL" => Signal::SIGKILL,
- "SIGUSR1" => Signal::SIGUSR1,
- "SIGSEGV" => Signal::SIGSEGV,
- "SIGUSR2" => Signal::SIGUSR2,
- "SIGPIPE" => Signal::SIGPIPE,
- "SIGALRM" => Signal::SIGALRM,
- "SIGTERM" => Signal::SIGTERM,
- #[cfg(all(
- any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ),
- not(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "sparc64"
- ))
- ))]
- "SIGSTKFLT" => Signal::SIGSTKFLT,
- "SIGCHLD" => Signal::SIGCHLD,
- "SIGCONT" => Signal::SIGCONT,
- "SIGSTOP" => Signal::SIGSTOP,
- "SIGTSTP" => Signal::SIGTSTP,
- "SIGTTIN" => Signal::SIGTTIN,
- "SIGTTOU" => Signal::SIGTTOU,
- "SIGURG" => Signal::SIGURG,
- "SIGXCPU" => Signal::SIGXCPU,
- "SIGXFSZ" => Signal::SIGXFSZ,
- "SIGVTALRM" => Signal::SIGVTALRM,
- "SIGPROF" => Signal::SIGPROF,
- "SIGWINCH" => Signal::SIGWINCH,
- #[cfg(not(target_os = "haiku"))]
- "SIGIO" => Signal::SIGIO,
- #[cfg(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- "SIGPWR" => Signal::SIGPWR,
- "SIGSYS" => Signal::SIGSYS,
- #[cfg(not(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux",
- target_os = "redox",
- target_os = "haiku"
- )))]
- "SIGEMT" => Signal::SIGEMT,
- #[cfg(not(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux",
- target_os = "redox",
- target_os = "haiku"
- )))]
- "SIGINFO" => Signal::SIGINFO,
- _ => return Err(Errno::EINVAL),
- })
- }
-}
-
-#[cfg(feature = "signal")]
-impl Signal {
- /// Returns name of signal.
- ///
- /// This function is equivalent to `<Signal as AsRef<str>>::as_ref()`,
- /// with difference that returned string is `'static`
- /// and not bound to `self`'s lifetime.
- pub const fn as_str(self) -> &'static str {
- match self {
- Signal::SIGHUP => "SIGHUP",
- Signal::SIGINT => "SIGINT",
- Signal::SIGQUIT => "SIGQUIT",
- Signal::SIGILL => "SIGILL",
- Signal::SIGTRAP => "SIGTRAP",
- Signal::SIGABRT => "SIGABRT",
- Signal::SIGBUS => "SIGBUS",
- Signal::SIGFPE => "SIGFPE",
- Signal::SIGKILL => "SIGKILL",
- Signal::SIGUSR1 => "SIGUSR1",
- Signal::SIGSEGV => "SIGSEGV",
- Signal::SIGUSR2 => "SIGUSR2",
- Signal::SIGPIPE => "SIGPIPE",
- Signal::SIGALRM => "SIGALRM",
- Signal::SIGTERM => "SIGTERM",
- #[cfg(all(
- any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ),
- not(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "sparc64"
- ))
- ))]
- Signal::SIGSTKFLT => "SIGSTKFLT",
- Signal::SIGCHLD => "SIGCHLD",
- Signal::SIGCONT => "SIGCONT",
- Signal::SIGSTOP => "SIGSTOP",
- Signal::SIGTSTP => "SIGTSTP",
- Signal::SIGTTIN => "SIGTTIN",
- Signal::SIGTTOU => "SIGTTOU",
- Signal::SIGURG => "SIGURG",
- Signal::SIGXCPU => "SIGXCPU",
- Signal::SIGXFSZ => "SIGXFSZ",
- Signal::SIGVTALRM => "SIGVTALRM",
- Signal::SIGPROF => "SIGPROF",
- Signal::SIGWINCH => "SIGWINCH",
- #[cfg(not(target_os = "haiku"))]
- Signal::SIGIO => "SIGIO",
- #[cfg(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- Signal::SIGPWR => "SIGPWR",
- Signal::SIGSYS => "SIGSYS",
- #[cfg(not(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux",
- target_os = "redox",
- target_os = "haiku"
- )))]
- Signal::SIGEMT => "SIGEMT",
- #[cfg(not(any(
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "linux",
- target_os = "redox",
- target_os = "haiku"
- )))]
- Signal::SIGINFO => "SIGINFO",
- }
- }
-}
-
-#[cfg(feature = "signal")]
-impl AsRef<str> for Signal {
- fn as_ref(&self) -> &str {
- self.as_str()
- }
-}
-
-#[cfg(feature = "signal")]
-impl fmt::Display for Signal {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str(self.as_ref())
- }
-}
-
-#[cfg(feature = "signal")]
-pub use self::Signal::*;
-
-#[cfg(target_os = "redox")]
-#[cfg(feature = "signal")]
-const SIGNALS: [Signal; 29] = [
- SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
- SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
- SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
- SIGPROF, SIGWINCH, SIGIO, SIGSYS,
-];
-#[cfg(target_os = "haiku")]
-#[cfg(feature = "signal")]
-const SIGNALS: [Signal; 28] = [
- SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
- SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
- SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
- SIGPROF, SIGWINCH, SIGSYS,
-];
-#[cfg(all(
- any(
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia"
- ),
- not(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "sparc64"
- ))
-))]
-#[cfg(feature = "signal")]
-const SIGNALS: [Signal; 31] = [
- SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
- SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGSTKFLT, SIGCHLD,
- SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ,
- SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
-];
-#[cfg(all(
- any(
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
- target_os = "fuchsia"
- ),
- any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")
-))]
-#[cfg(feature = "signal")]
-const SIGNALS: [Signal; 30] = [
- SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
- SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
- SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
- SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
-];
-#[cfg(not(any(
- target_os = "linux",
- target_os = "android",
- target_os = "fuchsia",
- target_os = "emscripten",
- target_os = "redox",
- target_os = "haiku"
-)))]
-#[cfg(feature = "signal")]
-const SIGNALS: [Signal; 31] = [
- SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
- SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
- SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
- SIGPROF, SIGWINCH, SIGIO, SIGSYS, SIGEMT, SIGINFO,
-];
-
-feature! {
-#![feature = "signal"]
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-/// Iterate through all signals defined by this operating system
-pub struct SignalIterator {
- next: usize,
-}
-
-impl Iterator for SignalIterator {
- type Item = Signal;
-
- fn next(&mut self) -> Option<Signal> {
- if self.next < SIGNALS.len() {
- let next_signal = SIGNALS[self.next];
- self.next += 1;
- Some(next_signal)
- } else {
- None
- }
- }
-}
-
-impl Signal {
- /// Iterate through all signals defined by this OS
- pub const fn iterator() -> SignalIterator {
- SignalIterator{next: 0}
- }
-}
-
-/// Alias for [`SIGABRT`]
-pub const SIGIOT : Signal = SIGABRT;
-/// Alias for [`SIGIO`]
-#[cfg(not(target_os = "haiku"))]
-pub const SIGPOLL : Signal = SIGIO;
-/// Alias for [`SIGSYS`]
-pub const SIGUNUSED : Signal = SIGSYS;
-
-cfg_if! {
- if #[cfg(target_os = "redox")] {
- type SaFlags_t = libc::c_ulong;
- } else if #[cfg(target_env = "uclibc")] {
- type SaFlags_t = libc::c_ulong;
- } else {
- type SaFlags_t = libc::c_int;
- }
-}
-}
-
-#[cfg(feature = "signal")]
-libc_bitflags! {
- /// Controls the behavior of a [`SigAction`]
- #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
- pub struct SaFlags: SaFlags_t {
- /// When catching a [`Signal::SIGCHLD`] signal, the signal will be
- /// generated only when a child process exits, not when a child process
- /// stops.
- SA_NOCLDSTOP;
- /// When catching a [`Signal::SIGCHLD`] signal, the system will not
- /// create zombie processes when children of the calling process exit.
- SA_NOCLDWAIT;
- /// Further occurrences of the delivered signal are not masked during
- /// the execution of the handler.
- SA_NODEFER;
- /// The system will deliver the signal to the process on a signal stack,
- /// specified by each thread with sigaltstack(2).
- SA_ONSTACK;
- /// The handler is reset back to the default at the moment the signal is
- /// delivered.
- SA_RESETHAND;
- /// Requests that certain system calls restart if interrupted by this
- /// signal. See the man page for complete details.
- SA_RESTART;
- /// This flag is controlled internally by Nix.
- SA_SIGINFO;
- }
-}
-
-#[cfg(feature = "signal")]
-libc_enum! {
- /// Specifies how certain functions should manipulate a signal mask
- #[repr(i32)]
- #[non_exhaustive]
- #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
- pub enum SigmaskHow {
- /// The new mask is the union of the current mask and the specified set.
- SIG_BLOCK,
- /// The new mask is the intersection of the current mask and the
- /// complement of the specified set.
- SIG_UNBLOCK,
- /// The current mask is replaced by the specified set.
- SIG_SETMASK,
- }
-}
-
-feature! {
-#![feature = "signal"]
-
-use crate::unistd::Pid;
-use std::iter::Extend;
-use std::iter::FromIterator;
-use std::iter::IntoIterator;
-
-/// Specifies a set of [`Signal`]s that may be blocked, waited for, etc.
-// We are using `transparent` here to be super sure that `SigSet`
-// is represented exactly like the `sigset_t` struct from C.
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct SigSet {
- sigset: libc::sigset_t
-}
-
-impl SigSet {
- /// Initialize to include all signals.
- #[doc(alias("sigfillset"))]
- pub fn all() -> SigSet {
- let mut sigset = mem::MaybeUninit::uninit();
- let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
-
- unsafe{ SigSet { sigset: sigset.assume_init() } }
- }
-
- /// Initialize to include nothing.
- #[doc(alias("sigemptyset"))]
- pub fn empty() -> SigSet {
- let mut sigset = mem::MaybeUninit::uninit();
- let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
-
- unsafe{ SigSet { sigset: sigset.assume_init() } }
- }
-
- /// Add the specified signal to the set.
- #[doc(alias("sigaddset"))]
- pub fn add(&mut self, signal: Signal) {
- unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
- }
-
- /// Remove all signals from this set.
- #[doc(alias("sigemptyset"))]
- pub fn clear(&mut self) {
- unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
- }
-
- /// Remove the specified signal from this set.
- #[doc(alias("sigdelset"))]
- pub fn remove(&mut self, signal: Signal) {
- unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
- }
-
- /// Return whether this set includes the specified signal.
- #[doc(alias("sigismember"))]
- pub fn contains(&self, signal: Signal) -> bool {
- let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
-
- match res {
- 1 => true,
- 0 => false,
- _ => unreachable!("unexpected value from sigismember"),
- }
- }
-
- /// Returns an iterator that yields the signals contained in this set.
- pub fn iter(&self) -> SigSetIter<'_> {
- self.into_iter()
- }
-
- /// Gets the currently blocked (masked) set of signals for the calling thread.
- pub fn thread_get_mask() -> Result<SigSet> {
- let mut oldmask = mem::MaybeUninit::uninit();
- do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?;
- Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
- }
-
- /// Sets the set of signals as the signal mask for the calling thread.
- pub fn thread_set_mask(&self) -> Result<()> {
- pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
- }
-
- /// Adds the set of signals to the signal mask for the calling thread.
- pub fn thread_block(&self) -> Result<()> {
- pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
- }
-
- /// Removes the set of signals from the signal mask for the calling thread.
- pub fn thread_unblock(&self) -> Result<()> {
- pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
- }
-
- /// Sets the set of signals as the signal mask, and returns the old mask.
- pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
- let mut oldmask = mem::MaybeUninit::uninit();
- do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?;
- Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
- }
-
- /// Suspends execution of the calling thread until one of the signals in the
- /// signal mask becomes pending, and returns the accepted signal.
- #[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn wait(&self) -> Result<Signal> {
- use std::convert::TryFrom;
-
- let mut signum = mem::MaybeUninit::uninit();
- let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
-
- Errno::result(res).map(|_| unsafe {
- Signal::try_from(signum.assume_init()).unwrap()
- })
- }
-
- /// Converts a `libc::sigset_t` object to a [`SigSet`] without checking whether the
- /// `libc::sigset_t` is already initialized.
- ///
- /// # Safety
- ///
- /// The `sigset` passed in must be a valid an initialized `libc::sigset_t` by calling either
- /// [`sigemptyset(3)`](https://man7.org/linux/man-pages/man3/sigemptyset.3p.html) or
- /// [`sigfillset(3)`](https://man7.org/linux/man-pages/man3/sigfillset.3p.html).
- /// Otherwise, the results are undefined.
- pub unsafe fn from_sigset_t_unchecked(sigset: libc::sigset_t) -> SigSet {
- SigSet { sigset }
- }
-}
-
-impl AsRef<libc::sigset_t> for SigSet {
- fn as_ref(&self) -> &libc::sigset_t {
- &self.sigset
- }
-}
-
-// TODO: Consider specialization for the case where T is &SigSet and libc::sigorset is available.
-impl Extend<Signal> for SigSet {
- fn extend<T>(&mut self, iter: T)
- where T: IntoIterator<Item = Signal> {
- for signal in iter {
- self.add(signal);
- }
- }
-}
-
-impl FromIterator<Signal> for SigSet {
- fn from_iter<T>(iter: T) -> Self
- where T: IntoIterator<Item = Signal> {
- let mut sigset = SigSet::empty();
- sigset.extend(iter);
- sigset
- }
-}
-
-/// Iterator for a [`SigSet`].
-///
-/// Call [`SigSet::iter`] to create an iterator.
-#[derive(Clone, Debug)]
-pub struct SigSetIter<'a> {
- sigset: &'a SigSet,
- inner: SignalIterator,
-}
-
-impl Iterator for SigSetIter<'_> {
- type Item = Signal;
- fn next(&mut self) -> Option<Signal> {
- loop {
- match self.inner.next() {
- None => return None,
- Some(signal) if self.sigset.contains(signal) => return Some(signal),
- Some(_signal) => continue,
- }
- }
- }
-}
-
-impl<'a> IntoIterator for &'a SigSet {
- type Item = Signal;
- type IntoIter = SigSetIter<'a>;
- fn into_iter(self) -> Self::IntoIter {
- SigSetIter { sigset: self, inner: Signal::iterator() }
- }
-}
-
-/// A signal handler.
-#[allow(unknown_lints)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum SigHandler {
- /// Default signal handling.
- SigDfl,
- /// Request that the signal be ignored.
- SigIgn,
- /// Use the given signal-catching function, which takes in the signal.
- Handler(extern fn(libc::c_int)),
- /// Use the given signal-catching function, which takes in the signal, information about how
- /// the signal was generated, and a pointer to the threads `ucontext_t`.
- #[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
-}
-
-/// Action to take on receipt of a signal. Corresponds to `sigaction`.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct SigAction {
- sigaction: libc::sigaction
-}
-
-impl SigAction {
- /// Creates a new action.
- ///
- /// The `SA_SIGINFO` bit in the `flags` argument is ignored (it will be set only if `handler`
- /// is the `SigAction` variant). `mask` specifies other signals to block during execution of
- /// the signal-catching function.
- pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
- unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
- (*p).sa_sigaction = match handler {
- SigHandler::SigDfl => libc::SIG_DFL,
- SigHandler::SigIgn => libc::SIG_IGN,
- SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
- #[cfg(not(target_os = "redox"))]
- SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
- };
- }
-
- let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
- unsafe {
- let p = s.as_mut_ptr();
- install_sig(p, handler);
- (*p).sa_flags = match handler {
- #[cfg(not(target_os = "redox"))]
- SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
- _ => (flags - SaFlags::SA_SIGINFO).bits(),
- };
- (*p).sa_mask = mask.sigset;
-
- SigAction { sigaction: s.assume_init() }
- }
- }
-
- /// Returns the flags set on the action.
- pub fn flags(&self) -> SaFlags {
- SaFlags::from_bits_truncate(self.sigaction.sa_flags)
- }
-
- /// Returns the set of signals that are blocked during execution of the action's
- /// signal-catching function.
- pub fn mask(&self) -> SigSet {
- SigSet { sigset: self.sigaction.sa_mask }
- }
-
- /// Returns the action's handler.
- pub fn handler(&self) -> SigHandler {
- match self.sigaction.sa_sigaction {
- libc::SIG_DFL => SigHandler::SigDfl,
- libc::SIG_IGN => SigHandler::SigIgn,
- #[cfg(not(target_os = "redox"))]
- p if self.flags().contains(SaFlags::SA_SIGINFO) =>
- SigHandler::SigAction(
- // Safe for one of two reasons:
- // * The SigHandler was created by SigHandler::new, in which
- // case the pointer is correct, or
- // * The SigHandler was created by signal or sigaction, which
- // are unsafe functions, so the caller should've somehow
- // ensured that it is correctly initialized.
- unsafe{
- *(&p as *const usize
- as *const extern fn(_, _, _))
- }
- as extern fn(_, _, _)),
- p => SigHandler::Handler(
- // Safe for one of two reasons:
- // * The SigHandler was created by SigHandler::new, in which
- // case the pointer is correct, or
- // * The SigHandler was created by signal or sigaction, which
- // are unsafe functions, so the caller should've somehow
- // ensured that it is correctly initialized.
- unsafe{
- *(&p as *const usize
- as *const extern fn(libc::c_int))
- }
- as extern fn(libc::c_int)),
- }
- }
-}
-
-/// Changes the action taken by a process on receipt of a specific signal.
-///
-/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`. On success, it returns the previous
-/// action for the given signal. If `sigaction` fails, no new signal handler is installed.
-///
-/// # Safety
-///
-/// * Signal handlers may be called at any point during execution, which limits
-/// what is safe to do in the body of the signal-catching function. Be certain
-/// to only make syscalls that are explicitly marked safe for signal handlers
-/// and only share global data using atomics.
-///
-/// * There is also no guarantee that the old signal handler was installed
-/// correctly. If it was installed by this crate, it will be. But if it was
-/// installed by, for example, C code, then there is no guarantee its function
-/// pointer is valid. In that case, this function effectively dereferences a
-/// raw pointer of unknown provenance.
-pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
- let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
-
- let res = libc::sigaction(signal as libc::c_int,
- &sigaction.sigaction as *const libc::sigaction,
- oldact.as_mut_ptr());
-
- Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
-}
-
-/// 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
-/// if the current handler is the default. The return value of `signal` is
-/// undefined after setting the handler with [`sigaction`][SigActionFn].
-///
-/// # Safety
-///
-/// If the pointer to the previous signal handler is invalid, undefined
-/// behavior could be invoked when casting it back to a [`SigAction`][SigActionStruct].
-///
-/// # Examples
-///
-/// Ignore `SIGINT`:
-///
-/// ```no_run
-/// # use nix::sys::signal::{self, Signal, SigHandler};
-/// unsafe { signal::signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
-/// ```
-///
-/// Use a signal handler to set a flag variable:
-///
-/// ```no_run
-/// # #[macro_use] extern crate lazy_static;
-/// # use std::convert::TryFrom;
-/// # use std::sync::atomic::{AtomicBool, Ordering};
-/// # use nix::sys::signal::{self, Signal, SigHandler};
-/// lazy_static! {
-/// static ref SIGNALED: AtomicBool = AtomicBool::new(false);
-/// }
-///
-/// extern fn handle_sigint(signal: libc::c_int) {
-/// let signal = Signal::try_from(signal).unwrap();
-/// SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
-/// }
-///
-/// fn main() {
-/// let handler = SigHandler::Handler(handle_sigint);
-/// unsafe { signal::signal(Signal::SIGINT, handler) }.unwrap();
-/// }
-/// ```
-///
-/// # Errors
-///
-/// Returns [`Error(Errno::EOPNOTSUPP)`] if `handler` is
-/// [`SigAction`][SigActionStruct]. Use [`sigaction`][SigActionFn] instead.
-///
-/// `signal` also returns any error from `libc::signal`, such as when an attempt
-/// is made to catch a signal that cannot be caught or to ignore a signal that
-/// cannot be ignored.
-///
-/// [`Error::UnsupportedOperation`]: ../../enum.Error.html#variant.UnsupportedOperation
-/// [SigActionStruct]: struct.SigAction.html
-/// [sigactionFn]: fn.sigaction.html
-pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
- let signal = signal as libc::c_int;
- let res = match handler {
- SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL),
- SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
- SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
- #[cfg(not(target_os = "redox"))]
- SigHandler::SigAction(_) => return Err(Errno::ENOTSUP),
- };
- Errno::result(res).map(|oldhandler| {
- match oldhandler {
- libc::SIG_DFL => SigHandler::SigDfl,
- libc::SIG_IGN => SigHandler::SigIgn,
- p => SigHandler::Handler(
- *(&p as *const usize
- as *const extern fn(libc::c_int))
- as extern fn(libc::c_int)),
- }
- })
-}
-
-fn do_pthread_sigmask(how: SigmaskHow,
- set: Option<&SigSet>,
- oldset: Option<*mut libc::sigset_t>) -> Result<()> {
- if set.is_none() && oldset.is_none() {
- return Ok(())
- }
-
- let res = unsafe {
- // if set or oldset is None, pass in null pointers instead
- libc::pthread_sigmask(how as libc::c_int,
- set.map_or_else(ptr::null::<libc::sigset_t>,
- |s| &s.sigset as *const libc::sigset_t),
- oldset.unwrap_or(ptr::null_mut())
- )
- };
-
- Errno::result(res).map(drop)
-}
-
-/// Manages the signal mask (set of blocked signals) for the calling thread.
-///
-/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
-/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
-/// and no modification will take place.
-///
-/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
-///
-/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
-/// and then it will be updated with `set`.
-///
-/// If both `set` and `oldset` is None, this function is a no-op.
-///
-/// 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<()>
-{
- do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ ))
-}
-
-/// Examine and change blocked signals.
-///
-/// For more information see the [`sigprocmask` man
-/// 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(())
- }
-
- let res = unsafe {
- // if set or oldset is None, pass in null pointers instead
- libc::sigprocmask(how as libc::c_int,
- set.map_or_else(ptr::null::<libc::sigset_t>,
- |s| &s.sigset as *const libc::sigset_t),
- oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
- |os| &mut os.sigset as *mut libc::sigset_t))
- };
-
- Errno::result(res).map(drop)
-}
-
-/// Send a signal to a process
-///
-/// # Arguments
-///
-/// * `pid` - Specifies which processes should receive the signal.
-/// - If positive, specifies an individual process.
-/// - If zero, the signal will be sent to all processes whose group
-/// ID is equal to the process group ID of the sender. This is a
-#[cfg_attr(target_os = "fuchsia", doc = "variant of `killpg`.")]
-#[cfg_attr(not(target_os = "fuchsia"), doc = "variant of [`killpg`].")]
-/// - If `-1` and the process has super-user privileges, the signal
-/// is sent to all processes exclusing system processes.
-/// - If less than `-1`, the signal is sent to all processes whose
-/// process group ID is equal to the absolute value of `pid`.
-/// * `signal` - Signal to send. If `None`, error checking is performed
-/// but no signal is actually sent.
-///
-/// See Also
-/// [`kill(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html)
-pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
- let res = unsafe { libc::kill(pid.into(),
- match signal.into() {
- Some(s) => s as libc::c_int,
- None => 0,
- }) };
-
- Errno::result(res).map(drop)
-}
-
-/// Send a signal to a process group
-///
-/// # Arguments
-///
-/// * `pgrp` - Process group to signal. If less then or equal 1, the behavior
-/// is platform-specific.
-/// * `signal` - Signal to send. If `None`, `killpg` will only preform error
-/// checking and won't send any signal.
-///
-/// See Also [killpg(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
-#[cfg(not(target_os = "fuchsia"))]
-pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
- let res = unsafe { libc::killpg(pgrp.into(),
- match signal.into() {
- Some(s) => s as libc::c_int,
- None => 0,
- }) };
-
- Errno::result(res).map(drop)
-}
-
-/// Send a signal to the current thread
-///
-/// See Also [raise(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html)
-pub fn raise(signal: Signal) -> Result<()> {
- let res = unsafe { libc::raise(signal as libc::c_int) };
-
- Errno::result(res).map(drop)
-}
-}
-
-feature! {
-#![any(feature = "aio", feature = "signal")]
-
-/// Identifies a thread for [`SigevNotify::SigevThreadId`]
-#[cfg(target_os = "freebsd")]
-pub type type_of_thread_id = libc::lwpid_t;
-/// Identifies a thread for [`SigevNotify::SigevThreadId`]
-#[cfg(target_os = "linux")]
-pub type type_of_thread_id = libc::pid_t;
-
-/// Specifies the notification method used by a [`SigEvent`]
-// sigval is actually a union of a int and a void*. But it's never really used
-// as a pointer, because neither libc nor the kernel ever dereference it. nix
-// therefore presents it as an intptr_t, which is how kevent uses it.
-#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum SigevNotify {
- /// No notification will be delivered
- SigevNone,
- /// Notify by delivering a signal to the process.
- SigevSignal {
- /// Signal to deliver
- signal: Signal,
- /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
- /// structure of the queued signal.
- si_value: libc::intptr_t
- },
- // Note: SIGEV_THREAD is not implemented because libc::sigevent does not
- // expose a way to set the union members needed by SIGEV_THREAD.
- /// Notify by delivering an event to a kqueue.
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- SigevKevent {
- /// File descriptor of the kqueue to notify.
- kq: RawFd,
- /// Will be contained in the kevent's `udata` field.
- udata: libc::intptr_t
- },
- /// Notify by delivering a signal to a thread.
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- SigevThreadId {
- /// Signal to send
- signal: Signal,
- /// LWP ID of the thread to notify
- thread_id: type_of_thread_id,
- /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
- /// structure of the queued signal.
- si_value: libc::intptr_t
- },
-}
-}
-
-#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-mod sigevent {
- feature! {
- #![any(feature = "aio", feature = "signal")]
-
- use std::mem;
- use std::ptr;
- use super::SigevNotify;
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- use super::type_of_thread_id;
-
- /// Used to request asynchronous notification of the completion of certain
- /// events, such as POSIX AIO and timers.
- #[repr(C)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct SigEvent {
- sigevent: libc::sigevent
- }
-
- impl SigEvent {
- /// **Note:** this constructor does not allow the user to set the
- /// `sigev_notify_kevent_flags` field. That's considered ok because on FreeBSD
- /// at least those flags don't do anything useful. That field is part of a
- /// union that shares space with the more genuinely useful fields.
- ///
- /// **Note:** This constructor also doesn't allow the caller to set the
- /// `sigev_notify_function` or `sigev_notify_attributes` fields, which are
- /// required for `SIGEV_THREAD`. That's considered ok because on no operating
- /// system is `SIGEV_THREAD` the most efficient way to deliver AIO
- /// notification. FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`.
- /// 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 {
- let mut sev = unsafe { mem::MaybeUninit::<libc::sigevent>::zeroed().assume_init() };
- sev.sigev_notify = match sigev_notify {
- SigevNotify::SigevNone => libc::SIGEV_NONE,
- SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
- #[cfg(target_os = "freebsd")]
- SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
- #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
- SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
- #[cfg(all(target_os = "linux", target_env = "uclibc"))]
- SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
- #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
- SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined
- };
- sev.sigev_signo = match sigev_notify {
- SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- SigevNotify::SigevKevent{ kq, ..} => kq,
- #[cfg(any(target_os = "linux", target_os = "freebsd"))]
- SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
- _ => 0
- };
- sev.sigev_value.sival_ptr = match sigev_notify {
- SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
- SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
- };
- SigEvent::set_tid(&mut sev, &sigev_notify);
- SigEvent{sigevent: sev}
- }
-
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
- sev.sigev_notify_thread_id = match *sigev_notify {
- SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
- _ => 0 as type_of_thread_id
- };
- }
-
- #[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
- fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
- }
-
- /// Return a copy of the inner structure
- pub fn sigevent(&self) -> libc::sigevent {
- self.sigevent
- }
-
- /// Returns a mutable pointer to the `sigevent` wrapped by `self`
- pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
- &mut self.sigevent
- }
- }
-
- impl<'a> From<&'a libc::sigevent> for SigEvent {
- fn from(sigevent: &libc::sigevent) -> Self {
- SigEvent{ sigevent: *sigevent }
- }
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- #[cfg(not(target_os = "redox"))]
- use std::thread;
-
- #[test]
- fn test_contains() {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- assert!(mask.contains(SIGUSR1));
- assert!(!mask.contains(SIGUSR2));
-
- let all = SigSet::all();
- assert!(all.contains(SIGUSR1));
- assert!(all.contains(SIGUSR2));
- }
-
- #[test]
- fn test_clear() {
- let mut set = SigSet::all();
- set.clear();
- for signal in Signal::iterator() {
- assert!(!set.contains(signal));
- }
- }
-
- #[test]
- fn test_from_str_round_trips() {
- for signal in Signal::iterator() {
- assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
- assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
- }
- }
-
- #[test]
- fn test_from_str_invalid_value() {
- let errval = Err(Errno::EINVAL);
- assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
- assert_eq!("kill".parse::<Signal>(), errval);
- assert_eq!("9".parse::<Signal>(), errval);
- }
-
- #[test]
- fn test_extend() {
- let mut one_signal = SigSet::empty();
- one_signal.add(SIGUSR1);
-
- let mut two_signals = SigSet::empty();
- two_signals.add(SIGUSR2);
- two_signals.extend(&one_signal);
-
- assert!(two_signals.contains(SIGUSR1));
- assert!(two_signals.contains(SIGUSR2));
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_set_mask() {
- thread::spawn(|| {
- let prev_mask = SigSet::thread_get_mask()
- .expect("Failed to get existing signal mask!");
-
- let mut test_mask = prev_mask;
- test_mask.add(SIGUSR1);
-
- test_mask.thread_set_mask().expect("assertion failed");
- let new_mask =
- SigSet::thread_get_mask().expect("Failed to get new mask!");
-
- assert!(new_mask.contains(SIGUSR1));
- assert!(!new_mask.contains(SIGUSR2));
-
- prev_mask
- .thread_set_mask()
- .expect("Failed to revert signal mask!");
- })
- .join()
- .unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_block() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- mask.thread_block().expect("assertion failed");
-
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
- })
- .join()
- .unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_unblock() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- mask.thread_unblock().expect("assertion failed");
-
- assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
- })
- .join()
- .unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_thread_signal_swap() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
- mask.thread_block().unwrap();
-
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
-
- let mut mask2 = SigSet::empty();
- mask2.add(SIGUSR2);
-
- let oldmask =
- mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK).unwrap();
-
- assert!(oldmask.contains(SIGUSR1));
- assert!(!oldmask.contains(SIGUSR2));
-
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
- })
- .join()
- .unwrap();
- }
-
- #[test]
- fn test_from_and_into_iterator() {
- let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]);
- let signals = sigset.into_iter().collect::<Vec<Signal>>();
- assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]);
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_sigaction() {
- thread::spawn(|| {
- extern "C" fn test_sigaction_handler(_: libc::c_int) {}
- extern "C" fn test_sigaction_action(
- _: libc::c_int,
- _: *mut libc::siginfo_t,
- _: *mut libc::c_void,
- ) {
- }
-
- let handler_sig = SigHandler::Handler(test_sigaction_handler);
-
- let flags =
- SaFlags::SA_ONSTACK | SaFlags::SA_RESTART | SaFlags::SA_SIGINFO;
-
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
-
- let action_sig = SigAction::new(handler_sig, flags, mask);
-
- assert_eq!(
- action_sig.flags(),
- SaFlags::SA_ONSTACK | SaFlags::SA_RESTART
- );
- assert_eq!(action_sig.handler(), handler_sig);
-
- mask = action_sig.mask();
- assert!(mask.contains(SIGUSR1));
- assert!(!mask.contains(SIGUSR2));
-
- let handler_act = SigHandler::SigAction(test_sigaction_action);
- let action_act = SigAction::new(handler_act, flags, mask);
- assert_eq!(action_act.handler(), handler_act);
-
- let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask);
- assert_eq!(action_dfl.handler(), SigHandler::SigDfl);
-
- let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
- assert_eq!(action_ign.handler(), SigHandler::SigIgn);
- })
- .join()
- .unwrap();
- }
-
- #[test]
- #[cfg(not(target_os = "redox"))]
- fn test_sigwait() {
- thread::spawn(|| {
- let mut mask = SigSet::empty();
- mask.add(SIGUSR1);
- mask.add(SIGUSR2);
- mask.thread_block().unwrap();
-
- raise(SIGUSR1).unwrap();
- assert_eq!(mask.wait().unwrap(), SIGUSR1);
- })
- .join()
- .unwrap();
- }
-
- #[test]
- fn test_from_sigset_t_unchecked() {
- let src_set = SigSet::empty();
- let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) };
-
- for signal in Signal::iterator() {
- assert!(!set.contains(signal));
- }
-
- let src_set = SigSet::all();
- let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) };
-
- for signal in Signal::iterator() {
- assert!(set.contains(signal));
- }
- }
-}
diff --git a/vendor/nix/src/sys/signalfd.rs b/vendor/nix/src/sys/signalfd.rs
deleted file mode 100644
index 095e59085..000000000
--- a/vendor/nix/src/sys/signalfd.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-//! Interface for the `signalfd` syscall.
-//!
-//! # Signal discarding
-//! When a signal can't be delivered to a process (or thread), it will become a pending signal.
-//! Failure to deliver could happen if the signal is blocked by every thread in the process or if
-//! the signal handler is still handling a previous signal.
-//!
-//! If a signal is sent to a process (or thread) that already has a pending signal of the same
-//! type, it will be discarded. This means that if signals of the same type are received faster than
-//! they are processed, some of those signals will be dropped. Because of this limitation,
-//! `signalfd` in itself cannot be used for reliable communication between processes or threads.
-//!
-//! Once the signal is unblocked, or the signal handler is finished, and a signal is still pending
-//! (ie. not consumed from a signalfd) it will be delivered to the signal handler.
-//!
-//! Please note that signal discarding is not specific to `signalfd`, but also happens with regular
-//! signal handlers.
-use crate::errno::Errno;
-pub use crate::sys::signal::{self, SigSet};
-use crate::unistd;
-use crate::Result;
-pub use libc::signalfd_siginfo as siginfo;
-
-use std::mem;
-use std::os::unix::io::{AsRawFd, RawFd};
-
-libc_bitflags! {
- pub struct SfdFlags: libc::c_int {
- SFD_NONBLOCK;
- SFD_CLOEXEC;
- }
-}
-
-pub const SIGNALFD_NEW: RawFd = -1;
-#[deprecated(since = "0.23.0", note = "use mem::size_of::<siginfo>() instead")]
-pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>();
-
-/// Creates a new file descriptor for reading signals.
-///
-/// **Important:** please read the module level documentation about signal discarding before using
-/// this function!
-///
-/// The `mask` parameter specifies the set of signals that can be accepted via this file descriptor.
-///
-/// 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](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(),
- ))
- }
-}
-
-/// A helper struct for creating, reading and closing a `signalfd` instance.
-///
-/// **Important:** please read the module level documentation about signal discarding before using
-/// this struct!
-///
-/// # Examples
-///
-/// ```
-/// # use nix::sys::signalfd::*;
-/// // Set the thread to block the SIGUSR1 signal, otherwise the default handler will be used
-/// let mut mask = SigSet::empty();
-/// mask.add(signal::SIGUSR1);
-/// mask.thread_block().unwrap();
-///
-/// // Signals are queued up on the file descriptor
-/// let mut sfd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
-///
-/// match sfd.read_signal() {
-/// // we caught a signal
-/// Ok(Some(sig)) => (),
-/// // there were no signals waiting (only happens when the SFD_NONBLOCK flag is set,
-/// // otherwise the read_signal call blocks)
-/// Ok(None) => (),
-/// Err(err) => (), // some error happend
-/// }
-/// ```
-#[derive(Debug, Eq, Hash, PartialEq)]
-pub struct SignalFd(RawFd);
-
-impl SignalFd {
- pub fn new(mask: &SigSet) -> Result<SignalFd> {
- Self::with_flags(mask, SfdFlags::empty())
- }
-
- pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result<SignalFd> {
- let fd = signalfd(SIGNALFD_NEW, mask, flags)?;
-
- Ok(SignalFd(fd))
- }
-
- pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
- signalfd(self.0, mask, SfdFlags::empty()).map(drop)
- }
-
- pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
- let mut buffer = mem::MaybeUninit::<siginfo>::uninit();
-
- let size = mem::size_of_val(&buffer);
- let res = Errno::result(unsafe {
- libc::read(self.0, buffer.as_mut_ptr() as *mut libc::c_void, size)
- })
- .map(|r| r as usize);
- match res {
- Ok(x) if x == size => Ok(Some(unsafe { buffer.assume_init() })),
- Ok(_) => unreachable!("partial read on signalfd"),
- Err(Errno::EAGAIN) => Ok(None),
- Err(error) => Err(error),
- }
- }
-}
-
-impl Drop for SignalFd {
- fn drop(&mut self) {
- let e = unistd::close(self.0);
- if !std::thread::panicking() && e == Err(Errno::EBADF) {
- panic!("Closing an invalid file descriptor!");
- };
- }
-}
-
-impl AsRawFd for SignalFd {
- fn as_raw_fd(&self) -> RawFd {
- self.0
- }
-}
-
-impl Iterator for SignalFd {
- type Item = siginfo;
-
- fn next(&mut self) -> Option<Self::Item> {
- match self.read_signal() {
- Ok(Some(sig)) => Some(sig),
- Ok(None) | Err(_) => None,
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn create_signalfd() {
- let mask = SigSet::empty();
- SignalFd::new(&mask).unwrap();
- }
-
- #[test]
- fn create_signalfd_with_opts() {
- let mask = SigSet::empty();
- SignalFd::with_flags(
- &mask,
- SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK,
- )
- .unwrap();
- }
-
- #[test]
- fn read_empty_signalfd() {
- let mask = SigSet::empty();
- let mut fd =
- SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
-
- let res = fd.read_signal();
- assert!(res.unwrap().is_none());
- }
-}
diff --git a/vendor/nix/src/sys/socket/addr.rs b/vendor/nix/src/sys/socket/addr.rs
deleted file mode 100644
index 4e565a5b6..000000000
--- a/vendor/nix/src/sys/socket/addr.rs
+++ /dev/null
@@ -1,3247 +0,0 @@
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "haiku",
- target_os = "fuchsia"
-))]
-#[cfg(feature = "net")]
-pub use self::datalink::LinkAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::vsock::VsockAddr;
-use super::sa_family_t;
-use crate::errno::Errno;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use crate::sys::socket::addr::alg::AlgAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use crate::sys::socket::addr::netlink::NetlinkAddr;
-#[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
-))]
-use crate::sys::socket::addr::sys_control::SysControlAddr;
-use crate::{NixPath, Result};
-use cfg_if::cfg_if;
-use memoffset::offset_of;
-use std::convert::TryInto;
-use std::ffi::OsStr;
-use std::hash::{Hash, Hasher};
-use std::os::unix::ffi::OsStrExt;
-#[cfg(any(target_os = "ios", target_os = "macos"))]
-use std::os::unix::io::RawFd;
-use std::path::Path;
-use std::{fmt, mem, net, ptr, slice};
-
-/// Convert a std::net::Ipv4Addr into the libc form.
-#[cfg(feature = "net")]
-pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr {
- static_assertions::assert_eq_size!(net::Ipv4Addr, libc::in_addr);
- // Safe because both types have the same memory layout, and no fancy Drop
- // impls.
- unsafe {
- mem::transmute(addr)
- }
-}
-
-/// Convert a std::net::Ipv6Addr into the libc form.
-#[cfg(feature = "net")]
-pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr {
- static_assertions::assert_eq_size!(net::Ipv6Addr, libc::in6_addr);
- // Safe because both are Newtype wrappers around the same libc type
- unsafe {
- mem::transmute(*addr)
- }
-}
-
-/// These constants specify the protocol family to be used
-/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
-///
-/// # References
-///
-/// [address_families(7)](https://man7.org/linux/man-pages/man7/address_families.7.html)
-// Should this be u8?
-#[repr(i32)]
-#[non_exhaustive]
-#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
-pub enum AddressFamily {
- /// 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)`](https://man7.org/linux/man-pages/man7/ip.7.html))
- Inet = libc::AF_INET,
- /// 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)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Netlink = libc::AF_NETLINK,
- /// 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"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Packet = libc::AF_PACKET,
- /// KEXT Controls and Notifications
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- System = libc::AF_SYSTEM,
- /// Amateur radio AX.25 protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Ax25 = libc::AF_AX25,
- /// IPX - Novell protocols
- Ipx = libc::AF_IPX,
- /// AppleTalk
- AppleTalk = libc::AF_APPLETALK,
- /// AX.25 packet layer protocol.
- /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetRom = libc::AF_NETROM,
- /// Can't be used for creating sockets; mostly used for bridge
- /// links in
- /// [rtnetlink(7)](https://man7.org/linux/man-pages/man7/rtnetlink.7.html)
- /// protocol commands.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Bridge = libc::AF_BRIDGE,
- /// Access to raw ATM PVCs
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- AtmPvc = libc::AF_ATMPVC,
- /// 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"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- X25 = libc::AF_X25,
- /// RATS (Radio Amateur Telecommunications Society) Open
- /// Systems environment (ROSE) AX.25 packet layer protocol.
- /// (see [netrom(4)](https://www.unix.com/man-page/linux/4/netrom/))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Rose = libc::AF_ROSE,
- /// DECet protocol sockets.
- #[cfg(not(target_os = "haiku"))]
- Decnet = libc::AF_DECnet,
- /// Reserved for "802.2LLC project"; never used.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetBeui = libc::AF_NETBEUI,
- /// This was a short-lived (between Linux 2.1.30 and
- /// 2.1.99pre2) protocol family for firewall upcalls.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Security = libc::AF_SECURITY,
- /// Key management protocol.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Key = libc::AF_KEY,
- #[allow(missing_docs)] // Not documented anywhere that I can find
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Ash = libc::AF_ASH,
- /// Acorn Econet protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Econet = libc::AF_ECONET,
- /// Access to ATM Switched Virtual Circuits
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- AtmSvc = libc::AF_ATMSVC,
- /// Reliable Datagram Sockets (RDS) protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Rds = libc::AF_RDS,
- /// IBM SNA
- #[cfg(not(target_os = "haiku"))]
- Sna = libc::AF_SNA,
- /// Socket interface over IrDA
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Irda = libc::AF_IRDA,
- /// Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE)
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Pppox = libc::AF_PPPOX,
- /// Legacy protocol for wide area network (WAN) connectivity that was used
- /// by Sangoma WAN cards
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Wanpipe = libc::AF_WANPIPE,
- /// Logical link control (IEEE 802.2 LLC) protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Llc = libc::AF_LLC,
- /// InfiniBand native addressing
- #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Ib = libc::AF_IB,
- /// Multiprotocol Label Switching
- #[cfg(all(target_os = "linux", not(target_env = "uclibc")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Mpls = libc::AF_MPLS,
- /// Controller Area Network automotive bus protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Can = libc::AF_CAN,
- /// TIPC, "cluster domain sockets" protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Tipc = libc::AF_TIPC,
- /// Bluetooth low-level socket protocol
- #[cfg(not(any(
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
- target_os = "solaris"
- )))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Bluetooth = libc::AF_BLUETOOTH,
- /// IUCV (inter-user communication vehicle) z/VM protocol for
- /// hypervisor-guest interaction
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Iucv = libc::AF_IUCV,
- /// Rx, Andrew File System remote procedure call protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- RxRpc = libc::AF_RXRPC,
- /// New "modular ISDN" driver interface protocol
- #[cfg(not(any(
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku"
- )))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Isdn = libc::AF_ISDN,
- /// Nokia cellular modem IPC/RPC interface
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Phonet = libc::AF_PHONET,
- /// IEEE 802.15.4 WPAN (wireless personal area network) raw packet protocol
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Ieee802154 = libc::AF_IEEE802154,
- /// Ericsson's Communication CPU to Application CPU interface (CAIF)
- /// protocol.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Caif = libc::AF_CAIF,
- /// Interface to kernel crypto API
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Alg = libc::AF_ALG,
- /// Near field communication
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Nfc = libc::AF_NFC,
- /// VMWare VSockets protocol for hypervisor-guest interaction.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Vsock = libc::AF_VSOCK,
- /// ARPANet IMP addresses
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ImpLink = libc::AF_IMPLINK,
- /// PUP protocols, e.g. BSP
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Pup = libc::AF_PUP,
- /// MIT CHAOS protocols
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Chaos = libc::AF_CHAOS,
- /// Novell and Xerox protocol
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Ns = libc::AF_NS,
- #[allow(missing_docs)] // Not documented anywhere that I can find
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Iso = libc::AF_ISO,
- /// Bell Labs virtual circuit switch ?
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Datakit = libc::AF_DATAKIT,
- /// CCITT protocols, X.25 etc
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Ccitt = libc::AF_CCITT,
- /// DEC Direct data link interface
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Dli = libc::AF_DLI,
- #[allow(missing_docs)] // Not documented anywhere that I can find
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Lat = libc::AF_LAT,
- /// NSC Hyperchannel
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Hylink = libc::AF_HYLINK,
- /// Link layer interface
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Link = libc::AF_LINK,
- /// connection-oriented IP, aka ST II
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Coip = libc::AF_COIP,
- /// Computer Network Technology
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Cnt = libc::AF_CNT,
- /// Native ATM access
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Natm = libc::AF_NATM,
- /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Unspec = libc::AF_UNSPEC,
-}
-
-impl AddressFamily {
- /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
- /// the `sa_family` field of a `sockaddr`.
- ///
- /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
- /// and System. Returns None for unsupported or unknown address families.
- pub const fn from_i32(family: i32) -> Option<AddressFamily> {
- match family {
- libc::AF_UNIX => Some(AddressFamily::Unix),
- libc::AF_INET => Some(AddressFamily::Inet),
- libc::AF_INET6 => Some(AddressFamily::Inet6),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_NETLINK => Some(AddressFamily::Netlink),
- #[cfg(any(target_os = "macos", target_os = "macos"))]
- libc::AF_SYSTEM => Some(AddressFamily::System),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_PACKET => Some(AddressFamily::Packet),
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- 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"))]
- libc::AF_VSOCK => Some(AddressFamily::Vsock),
- _ => None,
- }
- }
-}
-
-feature! {
-#![feature = "net"]
-
-#[deprecated(
- since = "0.24.0",
- note = "use SockaddrIn, SockaddrIn6, or SockaddrStorage instead"
-)]
-#[allow(missing_docs)] // Since they're all deprecated anyway
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum InetAddr {
- V4(libc::sockaddr_in),
- V6(libc::sockaddr_in6),
-}
-
-#[allow(missing_docs)] // It's deprecated anyway
-#[allow(deprecated)]
-impl InetAddr {
- #[allow(clippy::needless_update)] // It isn't needless on all OSes
- pub fn from_std(std: &net::SocketAddr) -> InetAddr {
- match *std {
- net::SocketAddr::V4(ref addr) => {
- InetAddr::V4(libc::sockaddr_in {
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "haiku", target_os = "hermit",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
- sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
- sin_family: AddressFamily::Inet as sa_family_t,
- sin_port: addr.port().to_be(), // network byte order
- sin_addr: Ipv4Addr::from_std(addr.ip()).0,
- .. unsafe { mem::zeroed() }
- })
- }
- net::SocketAddr::V6(ref addr) => {
- InetAddr::V6(libc::sockaddr_in6 {
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
- target_os = "haiku", target_os = "hermit",
- target_os = "ios", target_os = "macos",
- target_os = "netbsd", target_os = "openbsd"))]
- sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
- sin6_family: AddressFamily::Inet6 as sa_family_t,
- sin6_port: addr.port().to_be(), // network byte order
- sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
- sin6_flowinfo: addr.flowinfo(), // host byte order
- sin6_scope_id: addr.scope_id(), // host byte order
- .. unsafe { mem::zeroed() }
- })
- }
- }
- }
-
- #[allow(clippy::needless_update)] // It isn't needless on all OSes
- pub fn new(ip: IpAddr, port: u16) -> InetAddr {
- match ip {
- IpAddr::V4(ref ip) => {
- InetAddr::V4(libc::sockaddr_in {
- sin_family: AddressFamily::Inet as sa_family_t,
- sin_port: port.to_be(),
- sin_addr: ip.0,
- .. unsafe { mem::zeroed() }
- })
- }
- IpAddr::V6(ref ip) => {
- InetAddr::V6(libc::sockaddr_in6 {
- sin6_family: AddressFamily::Inet6 as sa_family_t,
- sin6_port: port.to_be(),
- sin6_addr: ip.0,
- .. unsafe { mem::zeroed() }
- })
- }
- }
- }
- /// Gets the IP address associated with this socket address.
- pub const fn ip(&self) -> IpAddr {
- match *self {
- InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
- InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
- }
- }
-
- /// Gets the port number associated with this socket address
- pub const fn port(&self) -> u16 {
- match *self {
- InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
- InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
- }
- }
-
- pub fn to_std(&self) -> net::SocketAddr {
- match *self {
- InetAddr::V4(ref sa) => net::SocketAddr::V4(
- net::SocketAddrV4::new(
- Ipv4Addr(sa.sin_addr).to_std(),
- self.port())),
- InetAddr::V6(ref sa) => net::SocketAddr::V6(
- net::SocketAddrV6::new(
- Ipv6Addr(sa.sin6_addr).to_std(),
- self.port(),
- sa.sin6_flowinfo,
- sa.sin6_scope_id)),
- }
- }
-
- #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
- pub fn to_str(&self) -> String {
- format!("{}", self)
- }
-}
-
-#[allow(deprecated)]
-impl fmt::Display for InetAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
- InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
- }
- }
-}
-
-/*
- *
- * ===== IpAddr =====
- *
- */
-#[allow(missing_docs)] // Since they're all deprecated anyway
-#[allow(deprecated)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[deprecated(
- since = "0.24.0",
- note = "Use std::net::IpAddr instead"
-)]
-pub enum IpAddr {
- V4(Ipv4Addr),
- V6(Ipv6Addr),
-}
-
-#[allow(deprecated)]
-#[allow(missing_docs)] // Since they're all deprecated anyway
-impl IpAddr {
- /// Create a new IpAddr that contains an IPv4 address.
- ///
- /// The result will represent the IP address a.b.c.d
- pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
- IpAddr::V4(Ipv4Addr::new(a, b, c, d))
- }
-
- /// Create a new IpAddr that contains an IPv6 address.
- ///
- /// The result will represent the IP address a:b:c:d:e:f
- #[allow(clippy::many_single_char_names)]
- #[allow(clippy::too_many_arguments)]
- pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
- IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
- }
-
- pub fn from_std(std: &net::IpAddr) -> IpAddr {
- match *std {
- net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
- net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
- }
- }
-
- pub const fn to_std(&self) -> net::IpAddr {
- match *self {
- IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
- IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
- }
- }
-}
-
-#[allow(deprecated)]
-impl fmt::Display for IpAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- IpAddr::V4(ref v4) => v4.fmt(f),
- IpAddr::V6(ref v6) => v6.fmt(f)
- }
- }
-}
-
-/*
- *
- * ===== Ipv4Addr =====
- *
- */
-
-#[deprecated(
- since = "0.24.0",
- note = "Use std::net::Ipv4Addr instead"
-)]
-#[allow(missing_docs)] // Since they're all deprecated anyway
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(transparent)]
-pub struct Ipv4Addr(pub libc::in_addr);
-
-#[allow(deprecated)]
-#[allow(missing_docs)] // Since they're all deprecated anyway
-impl Ipv4Addr {
- #[allow(clippy::identity_op)] // More readable this way
- pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
- let ip = (((a as u32) << 24) |
- ((b as u32) << 16) |
- ((c as u32) << 8) |
- ((d as u32) << 0)).to_be();
-
- Ipv4Addr(libc::in_addr { s_addr: ip })
- }
-
- // Use pass by reference for symmetry with Ipv6Addr::from_std
- #[allow(clippy::trivially_copy_pass_by_ref)]
- pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
- let bits = std.octets();
- Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
- }
-
- pub const fn any() -> Ipv4Addr {
- Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
- }
-
- pub const fn octets(self) -> [u8; 4] {
- let bits = u32::from_be(self.0.s_addr);
- [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
- }
-
- pub const fn to_std(self) -> net::Ipv4Addr {
- let bits = self.octets();
- net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
- }
-}
-
-#[allow(deprecated)]
-impl fmt::Display for Ipv4Addr {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- let octets = self.octets();
- write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
- }
-}
-
-/*
- *
- * ===== Ipv6Addr =====
- *
- */
-
-#[deprecated(
- since = "0.24.0",
- note = "Use std::net::Ipv6Addr instead"
-)]
-#[allow(missing_docs)] // Since they're all deprecated anyway
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(transparent)]
-pub struct Ipv6Addr(pub libc::in6_addr);
-
-// Note that IPv6 addresses are stored in big endian order on all architectures.
-// See https://tools.ietf.org/html/rfc1700 or consult your favorite search
-// engine.
-
-macro_rules! to_u8_array {
- ($($num:ident),*) => {
- [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
- }
-}
-
-macro_rules! to_u16_array {
- ($slf:ident, $($first:expr, $second:expr),*) => {
- [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
- }
-}
-
-#[allow(deprecated)]
-#[allow(missing_docs)] // Since they're all deprecated anyway
-impl Ipv6Addr {
- #[allow(clippy::many_single_char_names)]
- #[allow(clippy::too_many_arguments)]
- pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
- Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
- }
-
- pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
- let s = std.segments();
- Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
- }
-
- /// Return the eight 16-bit segments that make up this address
- pub const fn segments(&self) -> [u16; 8] {
- to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
- }
-
- pub const fn to_std(&self) -> net::Ipv6Addr {
- let s = self.segments();
- net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
- }
-}
-
-#[allow(deprecated)]
-impl fmt::Display for Ipv6Addr {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- self.to_std().fmt(fmt)
- }
-}
-}
-
-/// A wrapper around `sockaddr_un`.
-#[derive(Clone, Copy, Debug)]
-#[repr(C)]
-pub struct UnixAddr {
- // INVARIANT: sun & sun_len are valid as defined by docs for from_raw_parts
- sun: libc::sockaddr_un,
- /// The length of the valid part of `sun`, including the sun_family field
- /// but excluding any trailing nul.
- // On the BSDs, this field is built into sun
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))]
- sun_len: u8,
-}
-
-// linux man page unix(7) says there are 3 kinds of unix socket:
-// pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
-// unnamed: addrlen = sizeof(sa_family_t)
-// abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))]
-//
-// what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path)
-#[derive(PartialEq, Eq, Hash)]
-enum UnixAddrKind<'a> {
- Pathname(&'a Path),
- Unnamed,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Abstract(&'a [u8]),
-}
-impl<'a> UnixAddrKind<'a> {
- /// Safety: sun & sun_len must be valid
- unsafe fn get(sun: &'a libc::sockaddr_un, sun_len: u8) -> Self {
- assert!(sun_len as usize >= offset_of!(libc::sockaddr_un, sun_path));
- let path_len =
- sun_len as usize - offset_of!(libc::sockaddr_un, sun_path);
- if path_len == 0 {
- return Self::Unnamed;
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- if sun.sun_path[0] == 0 {
- let name = slice::from_raw_parts(
- sun.sun_path.as_ptr().add(1) as *const u8,
- path_len - 1,
- );
- return Self::Abstract(name);
- }
- let pathname =
- slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len);
- if pathname.last() == Some(&0) {
- // A trailing NUL is not considered part of the path, and it does
- // not need to be included in the addrlen passed to functions like
- // bind(). However, Linux adds a trailing NUL, even if one was not
- // originally present, when returning addrs from functions like
- // getsockname() (the BSDs do not do that). So we need to filter
- // out any trailing NUL here, so sockaddrs can round-trip through
- // the kernel and still compare equal.
- Self::Pathname(Path::new(OsStr::from_bytes(
- &pathname[0..pathname.len() - 1],
- )))
- } else {
- Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
- }
- }
-}
-
-impl UnixAddr {
- /// Create a new sockaddr_un representing a filesystem path.
- pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
- path.with_nix_path(|cstr| unsafe {
- let mut ret = libc::sockaddr_un {
- sun_family: AddressFamily::Unix as sa_family_t,
- ..mem::zeroed()
- };
-
- let bytes = cstr.to_bytes();
-
- if bytes.len() >= ret.sun_path.len() {
- return Err(Errno::ENAMETOOLONG);
- }
-
- let sun_len = (bytes.len()
- + offset_of!(libc::sockaddr_un, sun_path))
- .try_into()
- .unwrap();
-
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- {
- ret.sun_len = sun_len;
- }
- ptr::copy_nonoverlapping(
- bytes.as_ptr(),
- ret.sun_path.as_mut_ptr() as *mut u8,
- bytes.len(),
- );
-
- Ok(UnixAddr::from_raw_parts(ret, sun_len))
- })?
- }
-
- /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
- ///
- /// The leading nul byte for the abstract namespace is automatically added;
- /// thus the input `path` is expected to be the bare name, not NUL-prefixed.
- /// This is a Linux-specific extension, primarily used to allow chrooted
- /// processes to communicate with processes having a different filesystem view.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
- unsafe {
- let mut ret = libc::sockaddr_un {
- sun_family: AddressFamily::Unix as sa_family_t,
- ..mem::zeroed()
- };
-
- if path.len() >= ret.sun_path.len() {
- return Err(Errno::ENAMETOOLONG);
- }
- let sun_len =
- (path.len() + 1 + offset_of!(libc::sockaddr_un, sun_path))
- .try_into()
- .unwrap();
-
- // Abstract addresses are represented by sun_path[0] ==
- // b'\0', so copy starting one byte in.
- ptr::copy_nonoverlapping(
- path.as_ptr(),
- ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
- path.len(),
- );
-
- Ok(UnixAddr::from_raw_parts(ret, sun_len))
- }
- }
-
- /// Create a new `sockaddr_un` representing an "unnamed" unix socket address.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn new_unnamed() -> UnixAddr {
- let ret = libc::sockaddr_un {
- sun_family: AddressFamily::Unix as sa_family_t,
- .. unsafe { mem::zeroed() }
- };
-
- let sun_len: u8 = offset_of!(libc::sockaddr_un, sun_path).try_into().unwrap();
-
- unsafe { UnixAddr::from_raw_parts(ret, sun_len) }
- }
-
- /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `sun_len`
- /// is the size of the valid portion of the struct, excluding any trailing
- /// NUL.
- ///
- /// # Safety
- /// This pair of sockaddr_un & sun_len must be a valid unix addr, which
- /// means:
- /// - sun_len >= offset_of(sockaddr_un, sun_path)
- /// - sun_len <= sockaddr_un.sun_path.len() - offset_of(sockaddr_un, sun_path)
- /// - if this is a unix addr with a pathname, sun.sun_path is a
- /// fs path, not necessarily nul-terminated.
- pub(crate) unsafe fn from_raw_parts(
- sun: libc::sockaddr_un,
- sun_len: u8,
- ) -> UnixAddr {
- cfg_if! {
- if #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))]
- {
- UnixAddr { sun, sun_len }
- } else {
- assert_eq!(sun_len, sun.sun_len);
- UnixAddr {sun}
- }
- }
- }
-
- fn kind(&self) -> UnixAddrKind<'_> {
- // SAFETY: our sockaddr is always valid because of the invariant on the struct
- unsafe { UnixAddrKind::get(&self.sun, self.sun_len()) }
- }
-
- /// If this address represents a filesystem path, return that path.
- pub fn path(&self) -> Option<&Path> {
- match self.kind() {
- UnixAddrKind::Pathname(path) => Some(path),
- _ => None,
- }
- }
-
- /// If this address represents an abstract socket, return its name.
- ///
- /// For abstract sockets only the bare name is returned, without the
- /// leading NUL byte. `None` is returned for unnamed or path-backed sockets.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn as_abstract(&self) -> Option<&[u8]> {
- match self.kind() {
- UnixAddrKind::Abstract(name) => Some(name),
- _ => None,
- }
- }
-
- /// Check if this address is an "unnamed" unix socket address.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- #[inline]
- pub fn is_unnamed(&self) -> bool {
- matches!(self.kind(), UnixAddrKind::Unnamed)
- }
-
- /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
- #[inline]
- pub fn path_len(&self) -> usize {
- self.sun_len() as usize - offset_of!(libc::sockaddr_un, sun_path)
- }
- /// Returns a pointer to the raw `sockaddr_un` struct
- #[inline]
- pub fn as_ptr(&self) -> *const libc::sockaddr_un {
- &self.sun
- }
- /// Returns a mutable pointer to the raw `sockaddr_un` struct
- #[inline]
- pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
- &mut self.sun
- }
-
- fn sun_len(&self) -> u8 {
- cfg_if! {
- if #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))]
- {
- self.sun_len
- } else {
- self.sun.sun_len
- }
- }
- }
-}
-
-impl private::SockaddrLikePriv for UnixAddr {}
-impl SockaddrLike for UnixAddr {
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))]
- fn len(&self) -> libc::socklen_t {
- self.sun_len.into()
- }
-
- unsafe fn from_raw(
- addr: *const libc::sockaddr,
- len: Option<libc::socklen_t>,
- ) -> Option<Self>
- where
- Self: Sized,
- {
- if let Some(l) = len {
- if (l as usize) < offset_of!(libc::sockaddr_un, sun_path)
- || l > u8::MAX as libc::socklen_t
- {
- return None;
- }
- }
- if (*addr).sa_family as i32 != libc::AF_UNIX {
- return None;
- }
- let mut su: libc::sockaddr_un = mem::zeroed();
- let sup = &mut su as *mut libc::sockaddr_un as *mut u8;
- cfg_if! {
- if #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))] {
- let su_len = len.unwrap_or(
- mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
- );
- } else {
- let su_len = len.unwrap_or((*addr).sa_len as libc::socklen_t);
- }
- };
- ptr::copy(addr as *const u8, sup, su_len as usize);
- Some(Self::from_raw_parts(su, su_len as u8))
- }
-
- fn size() -> libc::socklen_t
- where
- Self: Sized,
- {
- mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
- }
-}
-
-impl AsRef<libc::sockaddr_un> for UnixAddr {
- fn as_ref(&self) -> &libc::sockaddr_un {
- &self.sun
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
- use fmt::Write;
- f.write_str("@\"")?;
- for &b in abs {
- use fmt::Display;
- char::from(b).escape_default().fmt(f)?;
- }
- f.write_char('"')?;
- Ok(())
-}
-
-impl fmt::Display for UnixAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self.kind() {
- UnixAddrKind::Pathname(path) => path.display().fmt(f),
- UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
- }
- }
-}
-
-impl PartialEq for UnixAddr {
- fn eq(&self, other: &UnixAddr) -> bool {
- self.kind() == other.kind()
- }
-}
-
-impl Eq for UnixAddr {}
-
-impl Hash for UnixAddr {
- fn hash<H: Hasher>(&self, s: &mut H) {
- self.kind().hash(s)
- }
-}
-
-/// Anything that, in C, can be cast back and forth to `sockaddr`.
-///
-/// Most implementors also implement `AsRef<libc::XXX>` to access their
-/// inner type read-only.
-#[allow(clippy::len_without_is_empty)]
-pub trait SockaddrLike: private::SockaddrLikePriv {
- /// Returns a raw pointer to the inner structure. Useful for FFI.
- fn as_ptr(&self) -> *const libc::sockaddr {
- self as *const Self as *const libc::sockaddr
- }
-
- /// Unsafe constructor from a variable length source
- ///
- /// Some C APIs from provide `len`, and others do not. If it's provided it
- /// will be validated. If not, it will be guessed based on the family.
- ///
- /// # Arguments
- ///
- /// - `addr`: raw pointer to something that can be cast to a
- /// `libc::sockaddr`. For example, `libc::sockaddr_in`,
- /// `libc::sockaddr_in6`, etc.
- /// - `len`: For fixed-width types like `sockaddr_in`, it will be
- /// validated if present and ignored if not. For variable-width
- /// types it is required and must be the total length of valid
- /// data. For example, if `addr` points to a
- /// named `sockaddr_un`, then `len` must be the length of the
- /// structure up to but not including the trailing NUL.
- ///
- /// # Safety
- ///
- /// `addr` must be valid for the specific type of sockaddr. `len`, if
- /// present, must not exceed the length of valid data in `addr`.
- unsafe fn from_raw(
- addr: *const libc::sockaddr,
- len: Option<libc::socklen_t>,
- ) -> Option<Self>
- where
- Self: Sized;
-
- /// Return the address family of this socket
- ///
- /// # Examples
- /// One common use is to match on the family of a union type, like this:
- /// ```
- /// # use nix::sys::socket::*;
- /// let fd = socket(AddressFamily::Inet, SockType::Stream,
- /// SockFlag::empty(), None).unwrap();
- /// let ss: SockaddrStorage = getsockname(fd).unwrap();
- /// match ss.family().unwrap() {
- /// AddressFamily::Inet => println!("{}", ss.as_sockaddr_in().unwrap()),
- /// AddressFamily::Inet6 => println!("{}", ss.as_sockaddr_in6().unwrap()),
- /// _ => println!("Unexpected address family")
- /// }
- /// ```
- fn family(&self) -> Option<AddressFamily> {
- // Safe since all implementors have a sa_family field at the same
- // address, and they're all repr(C)
- AddressFamily::from_i32(unsafe {
- (*(self as *const Self as *const libc::sockaddr)).sa_family as i32
- })
- }
-
- cfg_if! {
- if #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))] {
- /// Return the length of valid data in the sockaddr structure.
- ///
- /// For fixed-size sockaddrs, this should be the size of the
- /// structure. But for variable-sized types like [`UnixAddr`] it
- /// may be less.
- fn len(&self) -> libc::socklen_t {
- // Safe since all implementors have a sa_len field at the same
- // address, and they're all repr(transparent).
- // Robust for all implementors.
- unsafe {
- (*(self as *const Self as *const libc::sockaddr)).sa_len
- }.into()
- }
- } else {
- /// Return the length of valid data in the sockaddr structure.
- ///
- /// For fixed-size sockaddrs, this should be the size of the
- /// structure. But for variable-sized types like [`UnixAddr`] it
- /// may be less.
- fn len(&self) -> libc::socklen_t {
- // No robust default implementation is possible without an
- // sa_len field. Implementors with a variable size must
- // override this method.
- mem::size_of_val(self) as libc::socklen_t
- }
- }
- }
-
- /// Return the available space in the structure
- fn size() -> libc::socklen_t
- where
- Self: Sized,
- {
- mem::size_of::<Self>() as libc::socklen_t
- }
-}
-
-impl private::SockaddrLikePriv for () {
- fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
- ptr::null_mut()
- }
-}
-
-/// `()` can be used in place of a real Sockaddr when no address is expected,
-/// for example for a field of `Option<S> where S: SockaddrLike`.
-// If this RFC ever stabilizes, then ! will be a better choice.
-// https://github.com/rust-lang/rust/issues/35121
-impl SockaddrLike for () {
- fn as_ptr(&self) -> *const libc::sockaddr {
- ptr::null()
- }
-
- unsafe fn from_raw(
- _: *const libc::sockaddr,
- _: Option<libc::socklen_t>,
- ) -> Option<Self>
- where
- Self: Sized,
- {
- None
- }
-
- fn family(&self) -> Option<AddressFamily> {
- None
- }
-
- fn len(&self) -> libc::socklen_t {
- 0
- }
-}
-
-/// An IPv4 socket address
-// This is identical to net::SocketAddrV4. But the standard library
-// doesn't allow direct access to the libc fields, which we need. So we
-// reimplement it here.
-#[cfg(feature = "net")]
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct SockaddrIn(libc::sockaddr_in);
-
-#[cfg(feature = "net")]
-impl SockaddrIn {
- /// Returns the IP address associated with this socket address, in native
- /// endian.
- pub const fn ip(&self) -> libc::in_addr_t {
- u32::from_be(self.0.sin_addr.s_addr)
- }
-
- /// Creates a new socket address from IPv4 octets and a port number.
- pub fn new(a: u8, b: u8, c: u8, d: u8, port: u16) -> Self {
- Self(libc::sockaddr_in {
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"
- ))]
- sin_len: Self::size() as u8,
- sin_family: AddressFamily::Inet as sa_family_t,
- sin_port: u16::to_be(port),
- sin_addr: libc::in_addr {
- s_addr: u32::from_ne_bytes([a, b, c, d]),
- },
- sin_zero: unsafe { mem::zeroed() },
- })
- }
-
- /// Returns the port number associated with this socket address, in native
- /// endian.
- pub const fn port(&self) -> u16 {
- u16::from_be(self.0.sin_port)
- }
-}
-
-#[cfg(feature = "net")]
-impl private::SockaddrLikePriv for SockaddrIn {}
-#[cfg(feature = "net")]
-impl SockaddrLike for SockaddrIn {
- unsafe fn from_raw(
- addr: *const libc::sockaddr,
- len: Option<libc::socklen_t>,
- ) -> Option<Self>
- where
- Self: Sized,
- {
- if let Some(l) = len {
- if l != mem::size_of::<libc::sockaddr_in>() as libc::socklen_t {
- return None;
- }
- }
- if (*addr).sa_family as i32 != libc::AF_INET {
- return None;
- }
- Some(Self(ptr::read_unaligned(addr as *const _)))
- }
-}
-
-#[cfg(feature = "net")]
-impl AsRef<libc::sockaddr_in> for SockaddrIn {
- fn as_ref(&self) -> &libc::sockaddr_in {
- &self.0
- }
-}
-
-#[cfg(feature = "net")]
-impl fmt::Display for SockaddrIn {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let ne = u32::from_be(self.0.sin_addr.s_addr);
- let port = u16::from_be(self.0.sin_port);
- write!(
- f,
- "{}.{}.{}.{}:{}",
- ne >> 24,
- (ne >> 16) & 0xFF,
- (ne >> 8) & 0xFF,
- ne & 0xFF,
- port
- )
- }
-}
-
-#[cfg(feature = "net")]
-impl From<net::SocketAddrV4> for SockaddrIn {
- fn from(addr: net::SocketAddrV4) -> Self {
- Self(libc::sockaddr_in {
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "hermit",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- sin_len: mem::size_of::<libc::sockaddr_in>() as u8,
- sin_family: AddressFamily::Inet as sa_family_t,
- sin_port: addr.port().to_be(), // network byte order
- sin_addr: ipv4addr_to_libc(*addr.ip()),
- ..unsafe { mem::zeroed() }
- })
- }
-}
-
-#[cfg(feature = "net")]
-impl From<SockaddrIn> for net::SocketAddrV4 {
- fn from(addr: SockaddrIn) -> Self {
- net::SocketAddrV4::new(
- net::Ipv4Addr::from(addr.0.sin_addr.s_addr.to_ne_bytes()),
- u16::from_be(addr.0.sin_port),
- )
- }
-}
-
-#[cfg(feature = "net")]
-impl std::str::FromStr for SockaddrIn {
- type Err = net::AddrParseError;
-
- fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
- net::SocketAddrV4::from_str(s).map(SockaddrIn::from)
- }
-}
-
-/// An IPv6 socket address
-#[cfg(feature = "net")]
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct SockaddrIn6(libc::sockaddr_in6);
-
-#[cfg(feature = "net")]
-impl SockaddrIn6 {
- /// Returns the flow information associated with this address.
- pub const fn flowinfo(&self) -> u32 {
- self.0.sin6_flowinfo
- }
-
- /// Returns the IP address associated with this socket address.
- pub fn ip(&self) -> net::Ipv6Addr {
- net::Ipv6Addr::from(self.0.sin6_addr.s6_addr)
- }
-
- /// Returns the port number associated with this socket address, in native
- /// endian.
- pub const fn port(&self) -> u16 {
- u16::from_be(self.0.sin6_port)
- }
-
- /// Returns the scope ID associated with this address.
- pub const fn scope_id(&self) -> u32 {
- self.0.sin6_scope_id
- }
-}
-
-#[cfg(feature = "net")]
-impl private::SockaddrLikePriv for SockaddrIn6 {}
-#[cfg(feature = "net")]
-impl SockaddrLike for SockaddrIn6 {
- unsafe fn from_raw(
- addr: *const libc::sockaddr,
- len: Option<libc::socklen_t>,
- ) -> Option<Self>
- where
- Self: Sized,
- {
- if let Some(l) = len {
- if l != mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t {
- return None;
- }
- }
- if (*addr).sa_family as i32 != libc::AF_INET6 {
- return None;
- }
- Some(Self(ptr::read_unaligned(addr as *const _)))
- }
-}
-
-#[cfg(feature = "net")]
-impl AsRef<libc::sockaddr_in6> for SockaddrIn6 {
- fn as_ref(&self) -> &libc::sockaddr_in6 {
- &self.0
- }
-}
-
-#[cfg(feature = "net")]
-impl fmt::Display for SockaddrIn6 {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- // These things are really hard to display properly. Easier to let std
- // do it.
- let std = net::SocketAddrV6::new(
- self.ip(),
- self.port(),
- self.flowinfo(),
- self.scope_id(),
- );
- std.fmt(f)
- }
-}
-
-#[cfg(feature = "net")]
-impl From<net::SocketAddrV6> for SockaddrIn6 {
- fn from(addr: net::SocketAddrV6) -> Self {
- #[allow(clippy::needless_update)] // It isn't needless on Illumos
- Self(libc::sockaddr_in6 {
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "hermit",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8,
- sin6_family: AddressFamily::Inet6 as sa_family_t,
- sin6_port: addr.port().to_be(), // network byte order
- sin6_addr: ipv6addr_to_libc(addr.ip()),
- sin6_flowinfo: addr.flowinfo(), // host byte order
- sin6_scope_id: addr.scope_id(), // host byte order
- ..unsafe { mem::zeroed() }
- })
- }
-}
-
-#[cfg(feature = "net")]
-impl From<SockaddrIn6> for net::SocketAddrV6 {
- fn from(addr: SockaddrIn6) -> Self {
- net::SocketAddrV6::new(
- net::Ipv6Addr::from(addr.0.sin6_addr.s6_addr),
- u16::from_be(addr.0.sin6_port),
- addr.0.sin6_flowinfo,
- addr.0.sin6_scope_id,
- )
- }
-}
-
-#[cfg(feature = "net")]
-impl std::str::FromStr for SockaddrIn6 {
- type Err = net::AddrParseError;
-
- fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
- net::SocketAddrV6::from_str(s).map(SockaddrIn6::from)
- }
-}
-
-/// A container for any sockaddr type
-///
-/// Just like C's `sockaddr_storage`, this type is large enough to hold any type
-/// of sockaddr. It can be used as an argument with functions like
-/// [`bind`](super::bind) and [`getsockname`](super::getsockname). Though it is
-/// a union, it can be safely accessed through the `as_*` methods.
-///
-/// # Example
-/// ```
-/// # use nix::sys::socket::*;
-/// # use std::str::FromStr;
-/// let localhost = SockaddrIn::from_str("127.0.0.1:8081").unwrap();
-/// let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(),
-/// None).unwrap();
-/// bind(fd, &localhost).expect("bind");
-/// let ss: SockaddrStorage = getsockname(fd).expect("getsockname");
-/// assert_eq!(&localhost, ss.as_sockaddr_in().unwrap());
-/// ```
-#[derive(Clone, Copy, Eq)]
-#[repr(C)]
-pub union SockaddrStorage {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- alg: AlgAddr,
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- dl: LinkAddr,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- nl: NetlinkAddr,
- #[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
- ))]
- #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
- sctl: SysControlAddr,
- #[cfg(feature = "net")]
- sin: SockaddrIn,
- #[cfg(feature = "net")]
- sin6: SockaddrIn6,
- ss: libc::sockaddr_storage,
- su: UnixAddr,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- vsock: VsockAddr,
-}
-impl private::SockaddrLikePriv for SockaddrStorage {}
-impl SockaddrLike for SockaddrStorage {
- unsafe fn from_raw(
- addr: *const libc::sockaddr,
- l: Option<libc::socklen_t>,
- ) -> Option<Self>
- where
- Self: Sized,
- {
- if addr.is_null() {
- return None;
- }
- if let Some(len) = l {
- let ulen = len as usize;
- if ulen < offset_of!(libc::sockaddr, sa_data)
- || ulen > mem::size_of::<libc::sockaddr_storage>()
- {
- None
- } else {
- let mut ss: libc::sockaddr_storage = mem::zeroed();
- let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
- ptr::copy(addr as *const u8, ssp, len as usize);
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))]
- if i32::from(ss.ss_family) == libc::AF_UNIX {
- // Safe because we UnixAddr is strictly smaller than
- // SockaddrStorage, and we just initialized the structure.
- (*(&mut ss as *mut libc::sockaddr_storage as *mut UnixAddr)).sun_len = len as u8;
- }
- Some(Self { ss })
- }
- } else {
- // If length is not available and addr is of a fixed-length type,
- // copy it. If addr is of a variable length type and len is not
- // available, then there's nothing we can do.
- match (*addr).sa_family as i32 {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_ALG => {
- AlgAddr::from_raw(addr, l).map(|alg| Self { alg })
- }
- #[cfg(feature = "net")]
- libc::AF_INET => {
- SockaddrIn::from_raw(addr, l).map(|sin| Self { sin })
- }
- #[cfg(feature = "net")]
- libc::AF_INET6 => {
- SockaddrIn6::from_raw(addr, l).map(|sin6| Self { sin6 })
- }
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- libc::AF_LINK => {
- LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_NETLINK => {
- NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl })
- }
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg(feature = "net")]
- libc::AF_PACKET => {
- LinkAddr::from_raw(addr, l).map(|dl| Self { dl })
- }
- #[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
- ))]
- libc::AF_SYSTEM => {
- SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl })
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_VSOCK => {
- VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock })
- }
- _ => None,
- }
- }
- }
-
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))]
- fn len(&self) -> libc::socklen_t {
- match self.as_unix_addr() {
- // The UnixAddr type knows its own length
- Some(ua) => ua.len(),
- // For all else, we're just a boring SockaddrStorage
- None => mem::size_of_val(self) as libc::socklen_t
- }
- }
-}
-
-macro_rules! accessors {
- (
- $fname:ident,
- $fname_mut:ident,
- $sockty:ty,
- $family:expr,
- $libc_ty:ty,
- $field:ident) => {
- /// Safely and falliably downcast to an immutable reference
- pub fn $fname(&self) -> Option<&$sockty> {
- if self.family() == Some($family)
- && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
- {
- // Safe because family and len are validated
- Some(unsafe { &self.$field })
- } else {
- None
- }
- }
-
- /// Safely and falliably downcast to a mutable reference
- pub fn $fname_mut(&mut self) -> Option<&mut $sockty> {
- if self.family() == Some($family)
- && self.len() >= mem::size_of::<$libc_ty>() as libc::socklen_t
- {
- // Safe because family and len are validated
- Some(unsafe { &mut self.$field })
- } else {
- None
- }
- }
- };
-}
-
-impl SockaddrStorage {
- /// Downcast to an immutable `[UnixAddr]` reference.
- pub fn as_unix_addr(&self) -> Option<&UnixAddr> {
- cfg_if! {
- if #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))]
- {
- let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
- // Safe because UnixAddr is strictly smaller than
- // sockaddr_storage, and we're fully initialized
- let len = unsafe {
- (*(p as *const UnixAddr )).sun_len as usize
- };
- } else {
- let len = self.len() as usize;
- }
- }
- // Sanity checks
- if self.family() != Some(AddressFamily::Unix) ||
- len < offset_of!(libc::sockaddr_un, sun_path) ||
- len > mem::size_of::<libc::sockaddr_un>() {
- None
- } else {
- Some(unsafe{&self.su})
- }
- }
-
- /// Downcast to a mutable `[UnixAddr]` reference.
- pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> {
- cfg_if! {
- if #[cfg(any(target_os = "android",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux"
- ))]
- {
- let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
- // Safe because UnixAddr is strictly smaller than
- // sockaddr_storage, and we're fully initialized
- let len = unsafe {
- (*(p as *const UnixAddr )).sun_len as usize
- };
- } else {
- let len = self.len() as usize;
- }
- }
- // Sanity checks
- if self.family() != Some(AddressFamily::Unix) ||
- len < offset_of!(libc::sockaddr_un, sun_path) ||
- len > mem::size_of::<libc::sockaddr_un>() {
- None
- } else {
- Some(unsafe{&mut self.su})
- }
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr,
- AddressFamily::Alg, libc::sockaddr_alg, alg}
-
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg(feature = "net")]
- accessors! {
- as_link_addr, as_link_addr_mut, LinkAddr,
- AddressFamily::Packet, libc::sockaddr_ll, dl}
-
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- accessors! {
- as_link_addr, as_link_addr_mut, LinkAddr,
- AddressFamily::Link, libc::sockaddr_dl, dl}
-
- #[cfg(feature = "net")]
- accessors! {
- as_sockaddr_in, as_sockaddr_in_mut, SockaddrIn,
- AddressFamily::Inet, libc::sockaddr_in, sin}
-
- #[cfg(feature = "net")]
- accessors! {
- as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6,
- AddressFamily::Inet6, libc::sockaddr_in6, sin6}
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- accessors! {as_netlink_addr, as_netlink_addr_mut, NetlinkAddr,
- AddressFamily::Netlink, libc::sockaddr_nl, nl}
-
- #[cfg(all(feature = "ioctl", any(target_os = "ios", target_os = "macos")))]
- #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
- accessors! {as_sys_control_addr, as_sys_control_addr_mut, SysControlAddr,
- AddressFamily::System, libc::sockaddr_ctl, sctl}
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr,
- AddressFamily::Vsock, libc::sockaddr_vm, vsock}
-}
-
-impl fmt::Debug for SockaddrStorage {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("SockaddrStorage")
- // Safe because sockaddr_storage has the least specific
- // field types
- .field("ss", unsafe { &self.ss })
- .finish()
- }
-}
-
-impl fmt::Display for SockaddrStorage {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- unsafe {
- match self.ss.ss_family as i32 {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_ALG => self.alg.fmt(f),
- #[cfg(feature = "net")]
- libc::AF_INET => self.sin.fmt(f),
- #[cfg(feature = "net")]
- libc::AF_INET6 => self.sin6.fmt(f),
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- libc::AF_LINK => self.dl.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_NETLINK => self.nl.fmt(f),
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "fuchsia"
- ))]
- #[cfg(feature = "net")]
- libc::AF_PACKET => self.dl.fmt(f),
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg(feature = "ioctl")]
- libc::AF_SYSTEM => self.sctl.fmt(f),
- libc::AF_UNIX => self.su.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_VSOCK => self.vsock.fmt(f),
- _ => "<Address family unspecified>".fmt(f),
- }
- }
- }
-}
-
-#[cfg(feature = "net")]
-impl From<net::SocketAddrV4> for SockaddrStorage {
- fn from(s: net::SocketAddrV4) -> Self {
- unsafe {
- let mut ss: Self = mem::zeroed();
- ss.sin = SockaddrIn::from(s);
- ss
- }
- }
-}
-
-#[cfg(feature = "net")]
-impl From<net::SocketAddrV6> for SockaddrStorage {
- fn from(s: net::SocketAddrV6) -> Self {
- unsafe {
- let mut ss: Self = mem::zeroed();
- ss.sin6 = SockaddrIn6::from(s);
- ss
- }
- }
-}
-
-#[cfg(feature = "net")]
-impl From<net::SocketAddr> for SockaddrStorage {
- fn from(s: net::SocketAddr) -> Self {
- match s {
- net::SocketAddr::V4(sa4) => Self::from(sa4),
- net::SocketAddr::V6(sa6) => Self::from(sa6),
- }
- }
-}
-
-impl Hash for SockaddrStorage {
- fn hash<H: Hasher>(&self, s: &mut H) {
- unsafe {
- match self.ss.ss_family as i32 {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_ALG => self.alg.hash(s),
- #[cfg(feature = "net")]
- libc::AF_INET => self.sin.hash(s),
- #[cfg(feature = "net")]
- libc::AF_INET6 => self.sin6.hash(s),
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- libc::AF_LINK => self.dl.hash(s),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_NETLINK => self.nl.hash(s),
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "fuchsia"
- ))]
- #[cfg(feature = "net")]
- libc::AF_PACKET => self.dl.hash(s),
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg(feature = "ioctl")]
- libc::AF_SYSTEM => self.sctl.hash(s),
- libc::AF_UNIX => self.su.hash(s),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_VSOCK => self.vsock.hash(s),
- _ => self.ss.hash(s),
- }
- }
- }
-}
-
-impl PartialEq for SockaddrStorage {
- fn eq(&self, other: &Self) -> bool {
- unsafe {
- match (self.ss.ss_family as i32, other.ss.ss_family as i32) {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- (libc::AF_ALG, libc::AF_ALG) => self.alg == other.alg,
- #[cfg(feature = "net")]
- (libc::AF_INET, libc::AF_INET) => self.sin == other.sin,
- #[cfg(feature = "net")]
- (libc::AF_INET6, libc::AF_INET6) => self.sin6 == other.sin6,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl,
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- #[cfg(feature = "net")]
- (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl,
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg(feature = "ioctl")]
- (libc::AF_SYSTEM, libc::AF_SYSTEM) => self.sctl == other.sctl,
- (libc::AF_UNIX, libc::AF_UNIX) => self.su == other.su,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock,
- _ => false,
- }
- }
- }
-}
-
-mod private {
- pub trait SockaddrLikePriv {
- /// Returns a mutable raw pointer to the inner structure.
- ///
- /// # Safety
- ///
- /// This method is technically safe, but modifying the inner structure's
- /// `family` or `len` fields may result in violating Nix's invariants.
- /// It is best to use this method only with foreign functions that do
- /// not change the sockaddr type.
- fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
- self as *mut Self as *mut libc::sockaddr
- }
- }
-}
-
-/// Represents a socket address
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[deprecated(
- since = "0.24.0",
- note = "use SockaddrLike or SockaddrStorage instead"
-)]
-#[allow(missing_docs)] // Since they're all deprecated anyway
-#[allow(deprecated)]
-#[non_exhaustive]
-pub enum SockAddr {
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Inet(InetAddr),
- Unix(UnixAddr),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Netlink(NetlinkAddr),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Alg(AlgAddr),
- #[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
- ))]
- #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))]
- SysControl(SysControlAddr),
- /// Datalink address (MAC)
- #[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Link(LinkAddr),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- Vsock(VsockAddr),
-}
-
-#[allow(missing_docs)] // Since they're all deprecated anyway
-#[allow(deprecated)]
-impl SockAddr {
- feature! {
- #![feature = "net"]
- pub fn new_inet(addr: InetAddr) -> SockAddr {
- SockAddr::Inet(addr)
- }
- }
-
- pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
- Ok(SockAddr::Unix(UnixAddr::new(path)?))
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
- SockAddr::Netlink(NetlinkAddr::new(pid, groups))
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
- SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
- }
-
- feature! {
- #![feature = "ioctl"]
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
- SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl)
- }
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
- SockAddr::Vsock(VsockAddr::new(cid, port))
- }
-
- pub fn family(&self) -> AddressFamily {
- match *self {
- #[cfg(feature = "net")]
- SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
- #[cfg(feature = "net")]
- SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
- SockAddr::Unix(..) => AddressFamily::Unix,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Netlink(..) => AddressFamily::Netlink,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Alg(..) => AddressFamily::Alg,
- #[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
- ))]
- SockAddr::SysControl(..) => AddressFamily::System,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg(feature = "net")]
- SockAddr::Link(..) => AddressFamily::Packet,
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- SockAddr::Link(..) => AddressFamily::Link,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Vsock(..) => AddressFamily::Vsock,
- }
- }
-
- #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
- pub fn to_str(&self) -> String {
- format!("{}", self)
- }
-
- /// Creates a `SockAddr` struct from libc's sockaddr.
- ///
- /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
- /// Returns None for unsupported families.
- ///
- /// # Safety
- ///
- /// unsafe because it takes a raw pointer as argument. The caller must
- /// ensure that the pointer is valid.
- #[cfg(not(target_os = "fuchsia"))]
- #[cfg(feature = "net")]
- pub(crate) unsafe fn from_libc_sockaddr(
- addr: *const libc::sockaddr,
- ) -> Option<SockAddr> {
- if addr.is_null() {
- None
- } else {
- match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
- Some(AddressFamily::Unix) => None,
- #[cfg(feature = "net")]
- Some(AddressFamily::Inet) => Some(SockAddr::Inet(
- InetAddr::V4(ptr::read_unaligned(addr as *const _)),
- )),
- #[cfg(feature = "net")]
- Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
- InetAddr::V6(ptr::read_unaligned(addr as *const _)),
- )),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
- NetlinkAddr(ptr::read_unaligned(addr as *const _)),
- )),
- #[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
- ))]
- Some(AddressFamily::System) => Some(SockAddr::SysControl(
- SysControlAddr(ptr::read_unaligned(addr as *const _)),
- )),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg(feature = "net")]
- Some(AddressFamily::Packet) => Some(SockAddr::Link(LinkAddr(
- ptr::read_unaligned(addr as *const _),
- ))),
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- Some(AddressFamily::Link) => {
- let ether_addr =
- LinkAddr(ptr::read_unaligned(addr as *const _));
- if ether_addr.is_empty() {
- None
- } else {
- Some(SockAddr::Link(ether_addr))
- }
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(VsockAddr(
- ptr::read_unaligned(addr as *const _),
- ))),
- // Other address families are currently not supported and simply yield a None
- // entry instead of a proper conversion to a `SockAddr`.
- Some(_) | None => None,
- }
- }
- }
-
- /// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
- ///
- /// This is useful for interfacing with other libc functions that don't yet have nix wrappers.
- /// Returns a reference to the underlying data type (as a sockaddr reference) along
- /// with the size of the actual data type. sockaddr is commonly used as a proxy for
- /// a superclass as C doesn't support inheritance, so many functions that take
- /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back.
- pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
- match *self {
- #[cfg(feature = "net")]
- SockAddr::Inet(InetAddr::V4(ref addr)) => (
- // This cast is always allowed in C
- unsafe {
- &*(addr as *const libc::sockaddr_in
- as *const libc::sockaddr)
- },
- mem::size_of_val(addr) as libc::socklen_t,
- ),
- #[cfg(feature = "net")]
- SockAddr::Inet(InetAddr::V6(ref addr)) => (
- // This cast is always allowed in C
- unsafe {
- &*(addr as *const libc::sockaddr_in6
- as *const libc::sockaddr)
- },
- mem::size_of_val(addr) as libc::socklen_t,
- ),
- SockAddr::Unix(ref unix_addr) => (
- // This cast is always allowed in C
- unsafe {
- &*(&unix_addr.sun as *const libc::sockaddr_un
- as *const libc::sockaddr)
- },
- unix_addr.sun_len() as libc::socklen_t,
- ),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Netlink(NetlinkAddr(ref sa)) => (
- // This cast is always allowed in C
- unsafe {
- &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
- },
- mem::size_of_val(sa) as libc::socklen_t,
- ),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Alg(AlgAddr(ref sa)) => (
- // This cast is always allowed in C
- unsafe {
- &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
- },
- mem::size_of_val(sa) as libc::socklen_t,
- ),
- #[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
- ))]
- SockAddr::SysControl(SysControlAddr(ref sa)) => (
- // This cast is always allowed in C
- unsafe {
- &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
- },
- mem::size_of_val(sa) as libc::socklen_t,
- ),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg(feature = "net")]
- SockAddr::Link(LinkAddr(ref addr)) => (
- // This cast is always allowed in C
- unsafe {
- &*(addr as *const libc::sockaddr_ll
- as *const libc::sockaddr)
- },
- mem::size_of_val(addr) as libc::socklen_t,
- ),
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- SockAddr::Link(LinkAddr(ref addr)) => (
- // This cast is always allowed in C
- unsafe {
- &*(addr as *const libc::sockaddr_dl
- as *const libc::sockaddr)
- },
- mem::size_of_val(addr) as libc::socklen_t,
- ),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Vsock(VsockAddr(ref sa)) => (
- // This cast is always allowed in C
- unsafe {
- &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
- },
- mem::size_of_val(sa) as libc::socklen_t,
- ),
- }
- }
-}
-
-#[allow(deprecated)]
-impl fmt::Display for SockAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- #[cfg(feature = "net")]
- SockAddr::Inet(ref inet) => inet.fmt(f),
- SockAddr::Unix(ref unix) => unix.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Netlink(ref nl) => nl.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Alg(ref nl) => nl.fmt(f),
- #[cfg(all(
- feature = "ioctl",
- any(target_os = "ios", target_os = "macos")
- ))]
- SockAddr::SysControl(ref sc) => sc.fmt(f),
- #[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd"
- ))]
- #[cfg(feature = "net")]
- SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- SockAddr::Vsock(ref svm) => svm.fmt(f),
- }
- }
-}
-
-#[cfg(not(target_os = "fuchsia"))]
-#[cfg(feature = "net")]
-#[allow(deprecated)]
-impl private::SockaddrLikePriv for SockAddr {}
-#[cfg(not(target_os = "fuchsia"))]
-#[cfg(feature = "net")]
-#[allow(deprecated)]
-impl SockaddrLike for SockAddr {
- unsafe fn from_raw(
- addr: *const libc::sockaddr,
- _len: Option<libc::socklen_t>,
- ) -> Option<Self> {
- Self::from_libc_sockaddr(addr)
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub mod netlink {
- use super::*;
- use crate::sys::socket::addr::AddressFamily;
- use libc::{sa_family_t, sockaddr_nl};
- use std::{fmt, mem};
-
- /// Address for the Linux kernel user interface device.
- ///
- /// # References
- ///
- /// [netlink(7)](https://man7.org/linux/man-pages/man7/netlink.7.html)
- #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
- #[repr(transparent)]
- pub struct NetlinkAddr(pub(in super::super) sockaddr_nl);
-
- impl NetlinkAddr {
- /// Construct a new socket address from its port ID and multicast groups
- /// mask.
- pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
- let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
- addr.nl_family = AddressFamily::Netlink as sa_family_t;
- addr.nl_pid = pid;
- addr.nl_groups = groups;
-
- NetlinkAddr(addr)
- }
-
- /// Return the socket's port ID.
- pub const fn pid(&self) -> u32 {
- self.0.nl_pid
- }
-
- /// Return the socket's multicast groups mask
- pub const fn groups(&self) -> u32 {
- self.0.nl_groups
- }
- }
-
- impl private::SockaddrLikePriv for NetlinkAddr {}
- impl SockaddrLike for NetlinkAddr {
- unsafe fn from_raw(
- addr: *const libc::sockaddr,
- len: Option<libc::socklen_t>,
- ) -> Option<Self>
- where
- Self: Sized,
- {
- if let Some(l) = len {
- if l != mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t {
- return None;
- }
- }
- if (*addr).sa_family as i32 != libc::AF_NETLINK {
- return None;
- }
- Some(Self(ptr::read_unaligned(addr as *const _)))
- }
- }
-
- impl AsRef<libc::sockaddr_nl> for NetlinkAddr {
- fn as_ref(&self) -> &libc::sockaddr_nl {
- &self.0
- }
- }
-
- impl fmt::Display for NetlinkAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "pid: {} groups: {}", self.pid(), self.groups())
- }
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub mod alg {
- use super::*;
- use libc::{c_char, sockaddr_alg, AF_ALG};
- use std::ffi::CStr;
- use std::hash::{Hash, Hasher};
- use std::{fmt, mem, str};
-
- /// Socket address for the Linux kernel crypto API
- #[derive(Copy, Clone)]
- #[repr(transparent)]
- pub struct AlgAddr(pub(in super::super) sockaddr_alg);
-
- impl private::SockaddrLikePriv for AlgAddr {}
- impl SockaddrLike for AlgAddr {
- unsafe fn from_raw(
- addr: *const libc::sockaddr,
- l: Option<libc::socklen_t>,
- ) -> Option<Self>
- where
- Self: Sized,
- {
- if let Some(l) = l {
- if l != mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t
- {
- return None;
- }
- }
- if (*addr).sa_family as i32 != libc::AF_ALG {
- return None;
- }
- Some(Self(ptr::read_unaligned(addr as *const _)))
- }
- }
-
- impl AsRef<libc::sockaddr_alg> for AlgAddr {
- fn as_ref(&self) -> &libc::sockaddr_alg {
- &self.0
- }
- }
-
- // , PartialEq, Eq, Debug, Hash
- impl PartialEq for AlgAddr {
- fn eq(&self, other: &Self) -> bool {
- let (inner, other) = (self.0, other.0);
- (
- inner.salg_family,
- &inner.salg_type[..],
- inner.salg_feat,
- inner.salg_mask,
- &inner.salg_name[..],
- ) == (
- other.salg_family,
- &other.salg_type[..],
- other.salg_feat,
- other.salg_mask,
- &other.salg_name[..],
- )
- }
- }
-
- impl Eq for AlgAddr {}
-
- impl Hash for AlgAddr {
- fn hash<H: Hasher>(&self, s: &mut H) {
- let inner = self.0;
- (
- inner.salg_family,
- &inner.salg_type[..],
- inner.salg_feat,
- inner.salg_mask,
- &inner.salg_name[..],
- )
- .hash(s);
- }
- }
-
- impl AlgAddr {
- /// Construct an `AF_ALG` socket from its cipher name and type.
- pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
- let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
- addr.salg_family = AF_ALG as u16;
- addr.salg_type[..alg_type.len()]
- .copy_from_slice(alg_type.to_string().as_bytes());
- addr.salg_name[..alg_name.len()]
- .copy_from_slice(alg_name.to_string().as_bytes());
-
- AlgAddr(addr)
- }
-
- /// Return the socket's cipher type, for example `hash` or `aead`.
- pub fn alg_type(&self) -> &CStr {
- unsafe {
- CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char)
- }
- }
-
- /// Return the socket's cipher name, for example `sha1`.
- pub fn alg_name(&self) -> &CStr {
- unsafe {
- CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char)
- }
- }
- }
-
- impl fmt::Display for AlgAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(
- f,
- "type: {} alg: {}",
- self.alg_name().to_string_lossy(),
- self.alg_type().to_string_lossy()
- )
- }
- }
-
- impl fmt::Debug for AlgAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(self, f)
- }
- }
-}
-
-feature! {
-#![feature = "ioctl"]
-#[cfg(any(target_os = "ios", target_os = "macos"))]
-pub mod sys_control {
- use crate::sys::socket::addr::AddressFamily;
- use libc::{self, c_uchar};
- use std::{fmt, mem, ptr};
- use std::os::unix::io::RawFd;
- use crate::{Errno, Result};
- use super::{private, SockaddrLike};
-
- // FIXME: Move type into `libc`
- #[repr(C)]
- #[derive(Clone, Copy)]
- #[allow(missing_debug_implementations)]
- pub struct ctl_ioc_info {
- pub ctl_id: u32,
- pub ctl_name: [c_uchar; MAX_KCTL_NAME],
- }
-
- const CTL_IOC_MAGIC: u8 = b'N';
- const CTL_IOC_INFO: u8 = 3;
- const MAX_KCTL_NAME: usize = 96;
-
- ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
-
- /// Apple system control socket
- ///
- /// # References
- ///
- /// <https://developer.apple.com/documentation/kernel/sockaddr_ctl>
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- #[repr(transparent)]
- pub struct SysControlAddr(pub(in super::super) libc::sockaddr_ctl);
-
- impl private::SockaddrLikePriv for SysControlAddr {}
- impl SockaddrLike for SysControlAddr {
- unsafe fn from_raw(addr: *const libc::sockaddr, len: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
- {
- if let Some(l) = len {
- if l != mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t {
- return None;
- }
- }
- if (*addr).sa_family as i32 != libc::AF_SYSTEM {
- return None;
- }
- Some(Self(ptr::read_unaligned(addr as *const _)))
- }
- }
-
- impl AsRef<libc::sockaddr_ctl> for SysControlAddr {
- fn as_ref(&self) -> &libc::sockaddr_ctl {
- &self.0
- }
- }
-
- impl SysControlAddr {
- /// Construct a new `SysControlAddr` from its kernel unique identifier
- /// and unit number.
- pub const fn new(id: u32, unit: u32) -> SysControlAddr {
- let addr = libc::sockaddr_ctl {
- sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
- sc_family: AddressFamily::System as c_uchar,
- ss_sysaddr: libc::AF_SYS_CONTROL as u16,
- sc_id: id,
- sc_unit: unit,
- sc_reserved: [0; 5]
- };
-
- SysControlAddr(addr)
- }
-
- /// Construct a new `SysControlAddr` from its human readable name and
- /// unit number.
- pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
- if name.len() > MAX_KCTL_NAME {
- return Err(Errno::ENAMETOOLONG);
- }
-
- let mut ctl_name = [0; MAX_KCTL_NAME];
- ctl_name[..name.len()].clone_from_slice(name.as_bytes());
- let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
-
- unsafe { ctl_info(sockfd, &mut info)?; }
-
- Ok(SysControlAddr::new(info.ctl_id, unit))
- }
-
- /// Return the kernel unique identifier
- pub const fn id(&self) -> u32 {
- self.0.sc_id
- }
-
- /// Return the kernel controller private unit number.
- pub const fn unit(&self) -> u32 {
- self.0.sc_unit
- }
- }
-
- impl fmt::Display for SysControlAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Debug::fmt(self, f)
- }
- }
-}
-}
-
-#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-mod datalink {
- feature! {
- #![feature = "net"]
- use super::{fmt, mem, private, ptr, SockaddrLike};
-
- /// Hardware Address
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- #[repr(transparent)]
- pub struct LinkAddr(pub(in super::super) libc::sockaddr_ll);
-
- impl LinkAddr {
- /// Physical-layer protocol
- pub fn protocol(&self) -> u16 {
- self.0.sll_protocol
- }
-
- /// Interface number
- pub fn ifindex(&self) -> usize {
- self.0.sll_ifindex as usize
- }
-
- /// ARP hardware type
- pub fn hatype(&self) -> u16 {
- self.0.sll_hatype
- }
-
- /// Packet type
- pub fn pkttype(&self) -> u8 {
- self.0.sll_pkttype
- }
-
- /// Length of MAC address
- pub fn halen(&self) -> usize {
- self.0.sll_halen as usize
- }
-
- /// Physical-layer address (MAC)
- // Returns an Option just for cross-platform compatibility
- pub fn addr(&self) -> Option<[u8; 6]> {
- Some([
- self.0.sll_addr[0],
- self.0.sll_addr[1],
- self.0.sll_addr[2],
- self.0.sll_addr[3],
- self.0.sll_addr[4],
- self.0.sll_addr[5],
- ])
- }
- }
-
- impl fmt::Display for LinkAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- if let Some(addr) = self.addr() {
- write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
- addr[0],
- addr[1],
- addr[2],
- addr[3],
- addr[4],
- addr[5])
- } else {
- Ok(())
- }
- }
- }
- impl private::SockaddrLikePriv for LinkAddr {}
- impl SockaddrLike for LinkAddr {
- unsafe fn from_raw(addr: *const libc::sockaddr,
- len: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
- {
- if let Some(l) = len {
- if l != mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t {
- return None;
- }
- }
- if (*addr).sa_family as i32 != libc::AF_PACKET {
- return None;
- }
- Some(Self(ptr::read_unaligned(addr as *const _)))
- }
- }
-
- impl AsRef<libc::sockaddr_ll> for LinkAddr {
- fn as_ref(&self) -> &libc::sockaddr_ll {
- &self.0
- }
- }
-
- }
-}
-
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos",
- target_os = "netbsd",
- target_os = "haiku",
- target_os = "openbsd"
-))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-mod datalink {
- feature! {
- #![feature = "net"]
- use super::{fmt, mem, private, ptr, SockaddrLike};
-
- /// Hardware Address
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- #[repr(transparent)]
- pub struct LinkAddr(pub(in super::super) libc::sockaddr_dl);
-
- impl LinkAddr {
- /// interface index, if != 0, system given index for interface
- #[cfg(not(target_os = "haiku"))]
- pub fn ifindex(&self) -> usize {
- self.0.sdl_index as usize
- }
-
- /// Datalink type
- #[cfg(not(target_os = "haiku"))]
- pub fn datalink_type(&self) -> u8 {
- self.0.sdl_type
- }
-
- /// MAC address start position
- pub fn nlen(&self) -> usize {
- self.0.sdl_nlen as usize
- }
-
- /// link level address length
- pub fn alen(&self) -> usize {
- self.0.sdl_alen as usize
- }
-
- /// link layer selector length
- #[cfg(not(target_os = "haiku"))]
- pub fn slen(&self) -> usize {
- self.0.sdl_slen as usize
- }
-
- /// if link level address length == 0,
- /// or `sdl_data` not be larger.
- pub fn is_empty(&self) -> bool {
- let nlen = self.nlen();
- let alen = self.alen();
- let data_len = self.0.sdl_data.len();
-
- alen == 0 || nlen + alen >= data_len
- }
-
- /// Physical-layer address (MAC)
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- pub fn addr(&self) -> Option<[u8; 6]> {
- let nlen = self.nlen();
- let data = self.0.sdl_data;
-
- if self.is_empty() {
- None
- } else {
- Some([
- data[nlen] as u8,
- data[nlen + 1] as u8,
- data[nlen + 2] as u8,
- data[nlen + 3] as u8,
- data[nlen + 4] as u8,
- data[nlen + 5] as u8,
- ])
- }
- }
- }
-
- impl fmt::Display for LinkAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- if let Some(addr) = self.addr() {
- write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
- addr[0],
- addr[1],
- addr[2],
- addr[3],
- addr[4],
- addr[5])
- } else {
- Ok(())
- }
- }
- }
- impl private::SockaddrLikePriv for LinkAddr {}
- impl SockaddrLike for LinkAddr {
- unsafe fn from_raw(addr: *const libc::sockaddr,
- len: Option<libc::socklen_t>)
- -> Option<Self> where Self: Sized
- {
- if let Some(l) = len {
- if l != mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t {
- return None;
- }
- }
- if (*addr).sa_family as i32 != libc::AF_LINK {
- return None;
- }
- Some(Self(ptr::read_unaligned(addr as *const _)))
- }
- }
-
- impl AsRef<libc::sockaddr_dl> for LinkAddr {
- fn as_ref(&self) -> &libc::sockaddr_dl {
- &self.0
- }
- }
-
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub mod vsock {
- use super::*;
- use crate::sys::socket::addr::AddressFamily;
- use libc::{sa_family_t, sockaddr_vm};
- use std::hash::{Hash, Hasher};
- use std::{fmt, mem};
-
- /// Socket address for VMWare VSockets protocol
- ///
- /// # References
- ///
- /// [vsock(7)](https://man7.org/linux/man-pages/man7/vsock.7.html)
- #[derive(Copy, Clone)]
- #[repr(transparent)]
- pub struct VsockAddr(pub(in super::super) sockaddr_vm);
-
- impl private::SockaddrLikePriv for VsockAddr {}
- impl SockaddrLike for VsockAddr {
- unsafe fn from_raw(
- addr: *const libc::sockaddr,
- len: Option<libc::socklen_t>,
- ) -> Option<Self>
- where
- Self: Sized,
- {
- if let Some(l) = len {
- if l != mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t {
- return None;
- }
- }
- if (*addr).sa_family as i32 != libc::AF_VSOCK {
- return None;
- }
- Some(Self(ptr::read_unaligned(addr as *const _)))
- }
- }
-
- impl AsRef<libc::sockaddr_vm> for VsockAddr {
- fn as_ref(&self) -> &libc::sockaddr_vm {
- &self.0
- }
- }
-
- impl PartialEq for VsockAddr {
- fn eq(&self, other: &Self) -> bool {
- let (inner, other) = (self.0, other.0);
- (inner.svm_family, inner.svm_cid, inner.svm_port)
- == (other.svm_family, other.svm_cid, other.svm_port)
- }
- }
-
- impl Eq for VsockAddr {}
-
- impl Hash for VsockAddr {
- fn hash<H: Hasher>(&self, s: &mut H) {
- let inner = self.0;
- (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
- }
- }
-
- /// VSOCK Address
- ///
- /// The address for AF_VSOCK socket is defined as a combination of a
- /// 32-bit Context Identifier (CID) and a 32-bit port number.
- impl VsockAddr {
- /// Construct a `VsockAddr` from its raw fields.
- pub fn new(cid: u32, port: u32) -> VsockAddr {
- let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
- addr.svm_family = AddressFamily::Vsock as sa_family_t;
- addr.svm_cid = cid;
- addr.svm_port = port;
-
- VsockAddr(addr)
- }
-
- /// Context Identifier (CID)
- pub fn cid(&self) -> u32 {
- self.0.svm_cid
- }
-
- /// Port number
- pub fn port(&self) -> u32 {
- self.0.svm_port
- }
- }
-
- impl fmt::Display for VsockAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "cid: {} port: {}", self.cid(), self.port())
- }
- }
-
- impl fmt::Debug for VsockAddr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(self, f)
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- mod types {
- use super::*;
-
- #[test]
- fn test_ipv4addr_to_libc() {
- let s = std::net::Ipv4Addr::new(1, 2, 3, 4);
- let l = ipv4addr_to_libc(s);
- assert_eq!(l.s_addr, u32::to_be(0x01020304));
- }
-
- #[test]
- fn test_ipv6addr_to_libc() {
- let s = std::net::Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8);
- let l = ipv6addr_to_libc(&s);
- assert_eq!(
- l.s6_addr,
- [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8]
- );
- }
- }
-
- mod link {
- #![allow(clippy::cast_ptr_alignment)]
-
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "illumos"
- ))]
- use super::super::super::socklen_t;
- use super::*;
-
- /// Don't panic when trying to display an empty datalink address
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ))]
- #[test]
- fn test_datalink_display() {
- use super::super::LinkAddr;
- use std::mem;
-
- let la = LinkAddr(libc::sockaddr_dl {
- sdl_len: 56,
- sdl_family: 18,
- sdl_index: 5,
- sdl_type: 24,
- sdl_nlen: 3,
- sdl_alen: 0,
- sdl_slen: 0,
- ..unsafe { mem::zeroed() }
- });
- format!("{}", la);
- }
-
- #[cfg(all(
- any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ),
- target_endian = "little"
- ))]
- #[test]
- fn linux_loopback() {
- #[repr(align(2))]
- struct Raw([u8; 20]);
-
- let bytes = Raw([
- 17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0,
- ]);
- let sa = bytes.0.as_ptr() as *const libc::sockaddr;
- let len = None;
- let sock_addr =
- unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
- assert_eq!(sock_addr.family(), Some(AddressFamily::Packet));
- match sock_addr.as_link_addr() {
- Some(dl) => assert_eq!(dl.addr(), Some([1, 2, 3, 4, 5, 6])),
- None => panic!("Can't unwrap sockaddr storage"),
- }
- }
-
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[test]
- fn macos_loopback() {
- let bytes =
- [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
- let sa = bytes.as_ptr() as *const libc::sockaddr;
- let len = Some(bytes.len() as socklen_t);
- let sock_addr =
- unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
- assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
- match sock_addr.as_link_addr() {
- Some(dl) => {
- assert!(dl.addr().is_none());
- }
- None => panic!("Can't unwrap sockaddr storage"),
- }
- }
-
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[test]
- fn macos_tap() {
- let bytes = [
- 20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35,
- 76, -80,
- ];
- let ptr = bytes.as_ptr();
- let sa = ptr as *const libc::sockaddr;
- let len = Some(bytes.len() as socklen_t);
-
- let sock_addr =
- unsafe { SockaddrStorage::from_raw(sa, len).unwrap() };
- assert_eq!(sock_addr.family(), Some(AddressFamily::Link));
- match sock_addr.as_link_addr() {
- Some(dl) => {
- assert_eq!(dl.addr(), Some([24u8, 101, 144, 221, 76, 176]))
- }
- None => panic!("Can't unwrap sockaddr storage"),
- }
- }
-
- #[cfg(target_os = "illumos")]
- #[test]
- fn illumos_tap() {
- 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 len = Some(bytes.len() as socklen_t);
- let _sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) };
-
- assert!(_sock_addr.is_some());
-
- let sock_addr = _sock_addr.unwrap();
-
- assert_eq!(sock_addr.family().unwrap(), AddressFamily::Link);
-
- assert_eq!(
- sock_addr.as_link_addr().unwrap().addr(),
- Some([24u8, 101, 144, 221, 76, 176])
- );
- }
-
- #[test]
- fn size() {
- #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "illumos",
- target_os = "openbsd",
- target_os = "haiku"
- ))]
- let l = mem::size_of::<libc::sockaddr_dl>();
- #[cfg(any(
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux"
- ))]
- let l = mem::size_of::<libc::sockaddr_ll>();
- assert_eq!(LinkAddr::size() as usize, l);
- }
- }
-
- mod sockaddr_in {
- use super::*;
- use std::str::FromStr;
-
- #[test]
- fn display() {
- let s = "127.0.0.1:8080";
- let addr = SockaddrIn::from_str(s).unwrap();
- assert_eq!(s, format!("{}", addr));
- }
-
- #[test]
- fn size() {
- assert_eq!(
- mem::size_of::<libc::sockaddr_in>(),
- SockaddrIn::size() as usize
- );
- }
- }
-
- mod sockaddr_in6 {
- use super::*;
- use std::str::FromStr;
-
- #[test]
- fn display() {
- let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
- let addr = SockaddrIn6::from_str(s).unwrap();
- assert_eq!(s, format!("{}", addr));
- }
-
- #[test]
- fn size() {
- assert_eq!(
- mem::size_of::<libc::sockaddr_in6>(),
- SockaddrIn6::size() as usize
- );
- }
-
- #[test]
- // Ensure that we can convert to-and-from std::net variants without change.
- fn to_and_from() {
- let s = "[1234:5678:90ab:cdef::1111:2222]:8080";
- let mut nix_sin6 = SockaddrIn6::from_str(s).unwrap();
- nix_sin6.0.sin6_flowinfo = 0x12345678;
- nix_sin6.0.sin6_scope_id = 0x9abcdef0;
-
- let std_sin6 : std::net::SocketAddrV6 = nix_sin6.into();
- assert_eq!(nix_sin6, std_sin6.into());
- }
- }
-
- mod sockaddr_storage {
- use super::*;
-
- #[test]
- fn from_sockaddr_un_named() {
- let ua = UnixAddr::new("/var/run/mysock").unwrap();
- let ptr = ua.as_ptr() as *const libc::sockaddr;
- let ss = unsafe {
- SockaddrStorage::from_raw(ptr, Some(ua.len()))
- }.unwrap();
- assert_eq!(ss.len(), ua.len());
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[test]
- fn from_sockaddr_un_abstract_named() {
- let name = String::from("nix\0abstract\0test");
- let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap();
- let ptr = ua.as_ptr() as *const libc::sockaddr;
- let ss = unsafe {
- SockaddrStorage::from_raw(ptr, Some(ua.len()))
- }.unwrap();
- assert_eq!(ss.len(), ua.len());
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[test]
- fn from_sockaddr_un_abstract_unnamed() {
- let ua = UnixAddr::new_unnamed();
- let ptr = ua.as_ptr() as *const libc::sockaddr;
- let ss = unsafe {
- SockaddrStorage::from_raw(ptr, Some(ua.len()))
- }.unwrap();
- assert_eq!(ss.len(), ua.len());
- }
- }
-
- mod unixaddr {
- use super::*;
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[test]
- fn abstract_sun_path() {
- let name = String::from("nix\0abstract\0test");
- let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
-
- let sun_path1 =
- unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
- let sun_path2 = [
- 0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0,
- 116, 101, 115, 116,
- ];
- assert_eq!(sun_path1, sun_path2);
- }
-
- #[test]
- fn size() {
- assert_eq!(
- mem::size_of::<libc::sockaddr_un>(),
- UnixAddr::size() as usize
- );
- }
- }
-}
diff --git a/vendor/nix/src/sys/socket/mod.rs b/vendor/nix/src/sys/socket/mod.rs
deleted file mode 100644
index 8513b6fbe..000000000
--- a/vendor/nix/src/sys/socket/mod.rs
+++ /dev/null
@@ -1,2487 +0,0 @@
-//! Socket interface functions
-//!
-//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
-#[cfg(target_os = "linux")]
-#[cfg(feature = "uio")]
-use crate::sys::time::TimeSpec;
-#[cfg(feature = "uio")]
-use crate::sys::time::TimeVal;
-use crate::{errno::Errno, Result};
-use cfg_if::cfg_if;
-use libc::{
- self, c_int, c_void, iovec, size_t, socklen_t, CMSG_DATA, CMSG_FIRSTHDR,
- CMSG_LEN, CMSG_NXTHDR,
-};
-use std::convert::{TryFrom, TryInto};
-use std::io::{IoSlice, IoSliceMut};
-#[cfg(feature = "net")]
-use std::net;
-use std::os::unix::io::RawFd;
-use std::{mem, ptr, slice};
-
-#[deny(missing_docs)]
-mod addr;
-#[deny(missing_docs)]
-pub mod sockopt;
-
-/*
- *
- * ===== Re-exports =====
- *
- */
-
-pub use self::addr::{SockaddrLike, SockaddrStorage};
-
-#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
-#[allow(deprecated)]
-pub use self::addr::{AddressFamily, SockAddr, UnixAddr};
-#[cfg(any(target_os = "illumos", target_os = "solaris"))]
-#[allow(deprecated)]
-pub use self::addr::{AddressFamily, SockAddr, UnixAddr};
-#[allow(deprecated)]
-#[cfg(not(any(
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku"
-)))]
-#[cfg(feature = "net")]
-pub use self::addr::{
- InetAddr, IpAddr, Ipv4Addr, Ipv6Addr, LinkAddr, SockaddrIn, SockaddrIn6,
-};
-#[allow(deprecated)]
-#[cfg(any(
- target_os = "illumos",
- target_os = "solaris",
- target_os = "haiku"
-))]
-#[cfg(feature = "net")]
-pub use self::addr::{
- InetAddr, IpAddr, Ipv4Addr, Ipv6Addr, SockaddrIn, SockaddrIn6,
-};
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use crate::sys::socket::addr::alg::AlgAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use crate::sys::socket::addr::netlink::NetlinkAddr;
-#[cfg(any(target_os = "ios", target_os = "macos"))]
-#[cfg(feature = "ioctl")]
-pub use crate::sys::socket::addr::sys_control::SysControlAddr;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use crate::sys::socket::addr::vsock::VsockAddr;
-
-#[cfg(feature = "uio")]
-pub use libc::{cmsghdr, msghdr};
-pub use libc::{sa_family_t, sockaddr, sockaddr_storage, sockaddr_un};
-#[cfg(feature = "net")]
-pub use libc::{sockaddr_in, sockaddr_in6};
-
-// Needed by the cmsg_space macro
-#[doc(hidden)]
-pub use libc::{c_uint, CMSG_SPACE};
-
-#[cfg(feature = "net")]
-use crate::sys::socket::addr::{ipv4addr_to_libc, ipv6addr_to_libc};
-
-/// These constants are used to specify the communication semantics
-/// when creating a socket with [`socket()`](fn.socket.html)
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-#[repr(i32)]
-#[non_exhaustive]
-pub enum SockType {
- /// Provides sequenced, reliable, two-way, connection-
- /// based byte streams. An out-of-band data transmission
- /// mechanism may be supported.
- Stream = libc::SOCK_STREAM,
- /// Supports datagrams (connectionless, unreliable
- /// messages of a fixed maximum length).
- Datagram = libc::SOCK_DGRAM,
- /// Provides a sequenced, reliable, two-way connection-
- /// based data transmission path for datagrams of fixed
- /// maximum length; a consumer is required to read an
- /// entire packet with each input system call.
- SeqPacket = libc::SOCK_SEQPACKET,
- /// Provides raw network protocol access.
- Raw = libc::SOCK_RAW,
- /// Provides a reliable datagram layer that does not
- /// guarantee ordering.
- #[cfg(not(any(target_os = "haiku")))]
- Rdm = libc::SOCK_RDM,
-}
-// The TryFrom impl could've been derived using libc_enum!. But for
-// backwards-compatibility with Nix-0.25.0 we manually implement it, so as to
-// keep the old variant names.
-impl TryFrom<i32> for SockType {
- type Error = crate::Error;
-
- fn try_from(x: i32) -> Result<Self> {
- match x {
- libc::SOCK_STREAM => Ok(Self::Stream),
- libc::SOCK_DGRAM => Ok(Self::Datagram),
- libc::SOCK_SEQPACKET => Ok(Self::SeqPacket),
- libc::SOCK_RAW => Ok(Self::Raw),
- #[cfg(not(any(target_os = "haiku")))]
- libc::SOCK_RDM => Ok(Self::Rdm),
- _ => Err(Errno::EINVAL)
- }
- }
-}
-
-/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
-/// to specify the protocol to use.
-#[repr(i32)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[non_exhaustive]
-pub enum SockProtocol {
- /// TCP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
- Tcp = libc::IPPROTO_TCP,
- /// UDP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
- Udp = libc::IPPROTO_UDP,
- /// Raw sockets ([raw(7)](https://man7.org/linux/man-pages/man7/raw.7.html))
- Raw = libc::IPPROTO_RAW,
- /// 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))
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- KextEvent = libc::SYSPROTO_EVENT,
- /// Allows applications to configure and control a KEXT
- /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- KextControl = libc::SYSPROTO_CONTROL,
- /// Receives routing and link updates and may be used to modify the routing tables (both IPv4 and IPv6), IP addresses, link
- // parameters, neighbor setups, queueing disciplines, traffic classes and packet classifiers
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkRoute = libc::NETLINK_ROUTE,
- /// Reserved for user-mode socket protocols
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkUserSock = libc::NETLINK_USERSOCK,
- /// Query information about sockets of various protocol families from the kernel
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkSockDiag = libc::NETLINK_SOCK_DIAG,
- /// SELinux event notifications.
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkSELinux = libc::NETLINK_SELINUX,
- /// Open-iSCSI
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkISCSI = libc::NETLINK_ISCSI,
- /// Auditing
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkAudit = libc::NETLINK_AUDIT,
- /// Access to FIB lookup from user space
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkFIBLookup = libc::NETLINK_FIB_LOOKUP,
- /// Netfilter subsystem
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkNetFilter = libc::NETLINK_NETFILTER,
- /// SCSI Transports
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkSCSITransport = libc::NETLINK_SCSITRANSPORT,
- /// Infiniband RDMA
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkRDMA = libc::NETLINK_RDMA,
- /// Transport IPv6 packets from netfilter to user space. Used by ip6_queue kernel module.
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkIPv6Firewall = libc::NETLINK_IP6_FW,
- /// DECnet routing messages
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkDECNetRoutingMessage = libc::NETLINK_DNRTMSG,
- /// Kernel messages to user space
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT,
- /// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow
- /// configuration of the kernel crypto API.
- /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NetlinkCrypto = libc::NETLINK_CRYPTO,
- /// Non-DIX type protocol number defined for the Ethernet IEEE 802.3 interface that allows packets of all protocols
- /// defined in the interface to be received.
- /// ([ref](https://man7.org/linux/man-pages/man7/packet.7.html))
- // The protocol number is fed into the socket syscall in network byte order.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- EthAll = libc::ETH_P_ALL.to_be(),
-}
-
-#[cfg(any(target_os = "linux"))]
-libc_bitflags! {
- /// Configuration flags for `SO_TIMESTAMPING` interface
- ///
- /// For use with [`Timestamping`][sockopt::Timestamping].
- /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
- pub struct TimestampingFlag: c_uint {
- /// Report any software timestamps when available.
- SOF_TIMESTAMPING_SOFTWARE;
- /// Report hardware timestamps as generated by SOF_TIMESTAMPING_TX_HARDWARE when available.
- SOF_TIMESTAMPING_RAW_HARDWARE;
- /// Collect transmiting timestamps as reported by hardware
- SOF_TIMESTAMPING_TX_HARDWARE;
- /// Collect transmiting timestamps as reported by software
- SOF_TIMESTAMPING_TX_SOFTWARE;
- /// Collect receiving timestamps as reported by hardware
- SOF_TIMESTAMPING_RX_HARDWARE;
- /// Collect receiving timestamps as reported by software
- SOF_TIMESTAMPING_RX_SOFTWARE;
- }
-}
-
-libc_bitflags! {
- /// Additional socket options
- pub struct SockFlag: c_int {
- /// Set non-blocking mode on the new socket
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- SOCK_NONBLOCK;
- /// Set close-on-exec on the new descriptor
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- SOCK_CLOEXEC;
- /// Return `EPIPE` instead of raising `SIGPIPE`
- #[cfg(target_os = "netbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- SOCK_NOSIGPIPE;
- /// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)`
- /// to the DNS port (typically 53)
- #[cfg(target_os = "openbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- SOCK_DNS;
- }
-}
-
-libc_bitflags! {
- /// Flags for send/recv and their relatives
- pub struct MsgFlags: c_int {
- /// Sends or requests out-of-band data on sockets that support this notion
- /// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
- /// support out-of-band data.
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_OOB;
- /// Peeks at an incoming message. The data is treated as unread and the next
- /// [`recv()`](fn.recv.html)
- /// or similar function shall still return this data.
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_PEEK;
- /// Receive operation blocks until the full amount of data can be
- /// returned. The function may return smaller amount of data if a signal
- /// is caught, an error or disconnect occurs.
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_WAITALL;
- /// Enables nonblocking operation; if the operation would block,
- /// `EAGAIN` or `EWOULDBLOCK` is returned. This provides similar
- /// behavior to setting the `O_NONBLOCK` flag
- /// (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)](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.
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_DONTWAIT;
- /// Receive flags: Control Data was discarded (buffer too small)
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_CTRUNC;
- /// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram
- /// (since Linux 2.4.27/2.6.8),
- /// netlink (since Linux 2.6.22) and UNIX datagram (since Linux 3.4)
- /// sockets: return the real length of the packet or datagram, even
- /// when it was longer than the passed buffer. Not implemented for UNIX
- /// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets.
- ///
- /// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp).
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_TRUNC;
- /// Terminates a record (when this notion is supported, as for
- /// sockets of type [`SeqPacket`](enum.SockType.html)).
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_EOR;
- /// This flag specifies that queued errors should be received from
- /// the socket error queue. (For more details, see
- /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_ERRQUEUE;
- /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
- /// 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)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
- ///
- /// Only used in [`recvmsg`](fn.recvmsg.html) function.
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_CMSG_CLOEXEC;
- /// Requests not to send `SIGPIPE` errors when the other end breaks the connection.
- /// (For more details, see [send(2)](https://linux.die.net/man/2/send)).
- #[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "fuchsia",
- target_os = "haiku",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- #[allow(deprecated)] // Suppress useless warnings from libc PR 2963
- MSG_NOSIGNAL;
- }
-}
-
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- /// Unix credentials of the sending process.
- ///
- /// This struct is used with the `SO_PEERCRED` ancillary message
- /// and the `SCM_CREDENTIALS` control message for UNIX sockets.
- #[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- pub struct UnixCredentials(libc::ucred);
-
- impl UnixCredentials {
- /// Creates a new instance with the credentials of the current process
- pub fn new() -> Self {
- // Safe because these FFI functions are inherently safe
- unsafe {
- UnixCredentials(libc::ucred {
- pid: libc::getpid(),
- uid: libc::getuid(),
- gid: libc::getgid()
- })
- }
- }
-
- /// Returns the process identifier
- pub fn pid(&self) -> libc::pid_t {
- self.0.pid
- }
-
- /// Returns the user identifier
- pub fn uid(&self) -> libc::uid_t {
- self.0.uid
- }
-
- /// Returns the group identifier
- pub fn gid(&self) -> libc::gid_t {
- self.0.gid
- }
- }
-
- impl Default for UnixCredentials {
- fn default() -> Self {
- Self::new()
- }
- }
-
- impl From<libc::ucred> for UnixCredentials {
- fn from(cred: libc::ucred) -> Self {
- UnixCredentials(cred)
- }
- }
-
- impl From<UnixCredentials> for libc::ucred {
- fn from(uc: UnixCredentials) -> Self {
- uc.0
- }
- }
- } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
- /// Unix credentials of the sending process.
- ///
- /// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
- #[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- pub struct UnixCredentials(libc::cmsgcred);
-
- impl UnixCredentials {
- /// Returns the process identifier
- pub fn pid(&self) -> libc::pid_t {
- self.0.cmcred_pid
- }
-
- /// Returns the real user identifier
- pub fn uid(&self) -> libc::uid_t {
- self.0.cmcred_uid
- }
-
- /// Returns the effective user identifier
- pub fn euid(&self) -> libc::uid_t {
- self.0.cmcred_euid
- }
-
- /// Returns the real group identifier
- pub fn gid(&self) -> libc::gid_t {
- self.0.cmcred_gid
- }
-
- /// Returns a list group identifiers (the first one being the effective GID)
- pub fn groups(&self) -> &[libc::gid_t] {
- unsafe {
- slice::from_raw_parts(
- self.0.cmcred_groups.as_ptr() as *const libc::gid_t,
- self.0.cmcred_ngroups as _
- )
- }
- }
- }
-
- impl From<libc::cmsgcred> for UnixCredentials {
- fn from(cred: libc::cmsgcred) -> Self {
- UnixCredentials(cred)
- }
- }
- }
-}
-
-cfg_if! {
- if #[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"
- ))] {
- /// Return type of [`LocalPeerCred`](crate::sys::socket::sockopt::LocalPeerCred)
- #[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- pub struct XuCred(libc::xucred);
-
- impl XuCred {
- /// Structure layout version
- pub fn version(&self) -> u32 {
- self.0.cr_version
- }
-
- /// Effective user ID
- pub fn uid(&self) -> libc::uid_t {
- self.0.cr_uid
- }
-
- /// Returns a list of group identifiers (the first one being the
- /// effective GID)
- pub fn groups(&self) -> &[libc::gid_t] {
- &self.0.cr_groups
- }
- }
- }
-}
-
-feature! {
-#![feature = "net"]
-/// Request for multicast socket operations
-///
-/// This is a wrapper type around `ip_mreq`.
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct IpMembershipRequest(libc::ip_mreq);
-
-impl IpMembershipRequest {
- /// Instantiate a new `IpMembershipRequest`
- ///
- /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface.
- pub fn new(group: net::Ipv4Addr, interface: Option<net::Ipv4Addr>)
- -> Self
- {
- let imr_addr = match interface {
- None => net::Ipv4Addr::UNSPECIFIED,
- Some(addr) => addr
- };
- IpMembershipRequest(libc::ip_mreq {
- imr_multiaddr: ipv4addr_to_libc(group),
- imr_interface: ipv4addr_to_libc(imr_addr)
- })
- }
-}
-
-/// Request for ipv6 multicast socket operations
-///
-/// This is a wrapper type around `ipv6_mreq`.
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
-
-impl Ipv6MembershipRequest {
- /// Instantiate a new `Ipv6MembershipRequest`
- pub const fn new(group: net::Ipv6Addr) -> Self {
- Ipv6MembershipRequest(libc::ipv6_mreq {
- ipv6mr_multiaddr: ipv6addr_to_libc(&group),
- ipv6mr_interface: 0,
- })
- }
-}
-}
-
-feature! {
-#![feature = "uio"]
-
-/// Create a buffer large enough for storing some control messages as returned
-/// by [`recvmsg`](fn.recvmsg.html).
-///
-/// # Examples
-///
-/// ```
-/// # #[macro_use] extern crate nix;
-/// # use nix::sys::time::TimeVal;
-/// # use std::os::unix::io::RawFd;
-/// # fn main() {
-/// // Create a buffer for a `ControlMessageOwned::ScmTimestamp` message
-/// let _ = cmsg_space!(TimeVal);
-/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
-/// // with two file descriptors
-/// let _ = cmsg_space!([RawFd; 2]);
-/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
-/// // and a `ControlMessageOwned::ScmTimestamp` message
-/// let _ = cmsg_space!(RawFd, TimeVal);
-/// # }
-/// ```
-// Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a
-// stack-allocated array.
-#[macro_export]
-macro_rules! cmsg_space {
- ( $( $x:ty ),* ) => {
- {
- let mut space = 0;
- $(
- // CMSG_SPACE is always safe
- space += unsafe {
- $crate::sys::socket::CMSG_SPACE(::std::mem::size_of::<$x>() as $crate::sys::socket::c_uint)
- } as usize;
- )*
- Vec::<u8>::with_capacity(space)
- }
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-/// Contains outcome of sending or receiving a message
-///
-/// Use [`cmsgs`][RecvMsg::cmsgs] to access all the control messages present, and
-/// [`iovs`][RecvMsg::iovs`] to access underlying io slices.
-pub struct RecvMsg<'a, 's, S> {
- pub bytes: usize,
- cmsghdr: Option<&'a cmsghdr>,
- pub address: Option<S>,
- pub flags: MsgFlags,
- iobufs: std::marker::PhantomData<& 's()>,
- mhdr: msghdr,
-}
-
-impl<'a, S> RecvMsg<'a, '_, S> {
- /// Iterate over the valid control messages pointed to by this
- /// msghdr.
- pub fn cmsgs(&self) -> CmsgIterator {
- CmsgIterator {
- cmsghdr: self.cmsghdr,
- mhdr: &self.mhdr
- }
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub struct CmsgIterator<'a> {
- /// Control message buffer to decode from. Must adhere to cmsg alignment.
- cmsghdr: Option<&'a cmsghdr>,
- mhdr: &'a msghdr
-}
-
-impl<'a> Iterator for CmsgIterator<'a> {
- type Item = ControlMessageOwned;
-
- fn next(&mut self) -> Option<ControlMessageOwned> {
- match self.cmsghdr {
- None => None, // No more messages
- Some(hdr) => {
- // Get the data.
- // Safe if cmsghdr points to valid data returned by recvmsg(2)
- let cm = unsafe { Some(ControlMessageOwned::decode_from(hdr))};
- // Advance the internal pointer. Safe if mhdr and cmsghdr point
- // to valid data returned by recvmsg(2)
- self.cmsghdr = unsafe {
- let p = CMSG_NXTHDR(self.mhdr as *const _, hdr as *const _);
- p.as_ref()
- };
- cm
- }
- }
- }
-}
-
-/// A type-safe wrapper around a single control message, as used with
-/// [`recvmsg`](#fn.recvmsg).
-///
-/// [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
-// alignment issues.
-//
-// See https://github.com/nix-rust/nix/issues/999
-#[derive(Clone, Debug, Eq, PartialEq)]
-#[non_exhaustive]
-pub enum ControlMessageOwned {
- /// Received version of [`ControlMessage::ScmRights`]
- ScmRights(Vec<RawFd>),
- /// Received version of [`ControlMessage::ScmCredentials`]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ScmCredentials(UnixCredentials),
- /// Received version of [`ControlMessage::ScmCreds`]
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ScmCreds(UnixCredentials),
- /// A message of type `SCM_TIMESTAMP`, containing the time the
- /// packet was received by the kernel.
- ///
- /// See the kernel's explanation in "SO_TIMESTAMP" of
- /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt).
- ///
- /// # Examples
- ///
- /// ```
- /// # #[macro_use] extern crate nix;
- /// # use nix::sys::socket::*;
- /// # use nix::sys::time::*;
- /// # use std::io::{IoSlice, IoSliceMut};
- /// # use std::time::*;
- /// # use std::str::FromStr;
- /// # fn main() {
- /// // Set up
- /// let message = "Ohayō!".as_bytes();
- /// let in_socket = socket(
- /// AddressFamily::Inet,
- /// SockType::Datagram,
- /// SockFlag::empty(),
- /// None).unwrap();
- /// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
- /// let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
- /// bind(in_socket, &localhost).unwrap();
- /// let address: SockaddrIn = getsockname(in_socket).unwrap();
- /// // Get initial time
- /// let time0 = SystemTime::now();
- /// // Send the 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 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,
- /// Some(_) => panic!("Unexpected control message"),
- /// None => panic!("No control message")
- /// };
- /// // Check the final time
- /// let time1 = SystemTime::now();
- /// // the packet's received timestamp should lie in-between the two system
- /// // times, unless the system clock was adjusted in the meantime.
- /// let rduration = Duration::new(rtime.tv_sec() as u64,
- /// rtime.tv_usec() as u32 * 1000);
- /// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
- /// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
- /// // Close socket
- /// nix::unistd::close(in_socket).unwrap();
- /// # }
- /// ```
- ScmTimestamp(TimeVal),
- /// A set of nanosecond resolution timestamps
- ///
- /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
- #[cfg(all(target_os = "linux"))]
- ScmTimestampsns(Timestamps),
- /// Nanoseconds resolution timestamp
- ///
- /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
- #[cfg(all(target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ScmTimestampns(TimeSpec),
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- ))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv4PacketInfo(libc::in_pktinfo),
- #[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "openbsd",
- target_os = "netbsd",
- ))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv6PacketInfo(libc::in6_pktinfo),
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv4RecvIf(libc::sockaddr_dl),
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv4RecvDstAddr(libc::in_addr),
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv4OrigDstAddr(libc::sockaddr_in),
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv6OrigDstAddr(libc::sockaddr_in6),
-
- /// UDP Generic Receive Offload (GRO) allows receiving multiple UDP
- /// packets from a single sender.
- /// Fixed-size payloads are following one by one in a receive buffer.
- /// This Control Message indicates the size of all smaller packets,
- /// except, maybe, the last one.
- ///
- /// `UdpGroSegment` socket option should be enabled on a socket
- /// to allow receiving GRO packets.
- #[cfg(target_os = "linux")]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- UdpGroSegments(u16),
-
- /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
- /// ancilliary msg (cmsg) should be attached to recieved
- /// skbs indicating the number of packets dropped by the
- /// socket between the last recieved packet and this
- /// received packet.
- ///
- /// `RxqOvfl` socket option should be enabled on a socket
- /// to allow receiving the drop counter.
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- RxqOvfl(u32),
-
- /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv4RecvErr(libc::sock_extended_err, Option<sockaddr_in>),
- /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv6RecvErr(libc::sock_extended_err, Option<sockaddr_in6>),
-
- /// Catch-all variant for unimplemented cmsg types.
- #[doc(hidden)]
- Unknown(UnknownCmsg),
-}
-
-/// For representing packet timestamps via `SO_TIMESTAMPING` interface
-#[cfg(all(target_os = "linux"))]
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub struct Timestamps {
- /// software based timestamp, usually one containing data
- pub system: TimeSpec,
- /// legacy timestamp, usually empty
- pub hw_trans: TimeSpec,
- /// hardware based timestamp
- pub hw_raw: TimeSpec,
-}
-
-impl ControlMessageOwned {
- /// Decodes a `ControlMessageOwned` from raw bytes.
- ///
- /// This is only safe to call if the data is correct for the message type
- /// specified in the header. Normally, the kernel ensures that this is the
- /// case. "Correct" in this case includes correct length, alignment and
- /// actual content.
- // Clippy complains about the pointer alignment of `p`, not understanding
- // that it's being fed to a function that can handle that.
- #[allow(clippy::cast_ptr_alignment)]
- unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
- {
- let p = CMSG_DATA(header);
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- let len = header as *const _ as usize + header.cmsg_len as usize
- - p as usize;
- match (header.cmsg_level, header.cmsg_type) {
- (libc::SOL_SOCKET, libc::SCM_RIGHTS) => {
- let n = len / mem::size_of::<RawFd>();
- let mut fds = Vec::with_capacity(n);
- for i in 0..n {
- let fdp = (p as *const RawFd).add(i);
- fds.push(ptr::read_unaligned(fdp));
- }
- ControlMessageOwned::ScmRights(fds)
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
- let cred: libc::ucred = ptr::read_unaligned(p as *const _);
- ControlMessageOwned::ScmCredentials(cred.into())
- }
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- (libc::SOL_SOCKET, libc::SCM_CREDS) => {
- let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _);
- ControlMessageOwned::ScmCreds(cred.into())
- }
- #[cfg(not(target_os = "haiku"))]
- (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
- 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(all(target_os = "linux"))]
- (libc::SOL_SOCKET, libc::SCM_TIMESTAMPING) => {
- let tp = p as *const libc::timespec;
- let ts: libc::timespec = ptr::read_unaligned(tp);
- let system = TimeSpec::from(ts);
- let ts: libc::timespec = ptr::read_unaligned(tp.add(1));
- let hw_trans = TimeSpec::from(ts);
- let ts: libc::timespec = ptr::read_unaligned(tp.add(2));
- let hw_raw = TimeSpec::from(ts);
- let timestamping = Timestamps { system, hw_trans, hw_raw };
- ControlMessageOwned::ScmTimestampsns(timestamping)
- }
- #[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"
- ))]
- #[cfg(feature = "net")]
- (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
- let info = ptr::read_unaligned(p as *const libc::in6_pktinfo);
- ControlMessageOwned::Ipv6PacketInfo(info)
- }
- #[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- ))]
- #[cfg(feature = "net")]
- (libc::IPPROTO_IP, libc::IP_PKTINFO) => {
- let info = ptr::read_unaligned(p as *const libc::in_pktinfo);
- ControlMessageOwned::Ipv4PacketInfo(info)
- }
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
- #[cfg(feature = "net")]
- (libc::IPPROTO_IP, libc::IP_RECVIF) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl);
- ControlMessageOwned::Ipv4RecvIf(dl)
- },
- #[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- ))]
- #[cfg(feature = "net")]
- (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::in_addr);
- ControlMessageOwned::Ipv4RecvDstAddr(dl)
- },
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
- #[cfg(feature = "net")]
- (libc::IPPROTO_IP, libc::IP_ORIGDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_in);
- ControlMessageOwned::Ipv4OrigDstAddr(dl)
- },
- #[cfg(target_os = "linux")]
- #[cfg(feature = "net")]
- (libc::SOL_UDP, libc::UDP_GRO) => {
- let gso_size: u16 = ptr::read_unaligned(p as *const _);
- ControlMessageOwned::UdpGroSegments(gso_size)
- },
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- (libc::SOL_SOCKET, libc::SO_RXQ_OVFL) => {
- let drop_counter = ptr::read_unaligned(p as *const u32);
- ControlMessageOwned::RxqOvfl(drop_counter)
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg(feature = "net")]
- (libc::IPPROTO_IP, libc::IP_RECVERR) => {
- let (err, addr) = Self::recv_err_helper::<sockaddr_in>(p, len);
- ControlMessageOwned::Ipv4RecvErr(err, addr)
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg(feature = "net")]
- (libc::IPPROTO_IPV6, libc::IPV6_RECVERR) => {
- let (err, addr) = Self::recv_err_helper::<sockaddr_in6>(p, len);
- ControlMessageOwned::Ipv6RecvErr(err, addr)
- },
- #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
- #[cfg(feature = "net")]
- (libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR) => {
- let dl = ptr::read_unaligned(p as *const libc::sockaddr_in6);
- ControlMessageOwned::Ipv6OrigDstAddr(dl)
- },
- (_, _) => {
- let sl = slice::from_raw_parts(p, len);
- let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(sl));
- ControlMessageOwned::Unknown(ucmsg)
- }
- }
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg(feature = "net")]
- #[allow(clippy::cast_ptr_alignment)] // False positive
- unsafe fn recv_err_helper<T>(p: *mut libc::c_uchar, len: usize) -> (libc::sock_extended_err, Option<T>) {
- let ee = p as *const libc::sock_extended_err;
- let err = ptr::read_unaligned(ee);
-
- // For errors originating on the network, SO_EE_OFFENDER(ee) points inside the p[..len]
- // CMSG_DATA buffer. For local errors, there is no address included in the control
- // message, and SO_EE_OFFENDER(ee) points beyond the end of the buffer. So, we need to
- // validate that the address object is in-bounds before we attempt to copy it.
- let addrp = libc::SO_EE_OFFENDER(ee) as *const T;
-
- if addrp.offset(1) as usize - (p as usize) > len {
- (err, None)
- } else {
- (err, Some(ptr::read_unaligned(addrp)))
- }
- }
-}
-
-/// A type-safe zero-copy wrapper around a single control message, as used wih
-/// [`sendmsg`](#fn.sendmsg). More types may be added to this enum; do not
-/// exhaustively pattern-match it.
-///
-/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-#[non_exhaustive]
-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](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
- /// swallow all but the first `ScmRights` message or fail with `EINVAL`.
- /// Instead, you can put all fds to be passed into a single `ScmRights`
- /// message.
- ScmRights(&'a [RawFd]),
- /// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of
- /// a process connected to the socket.
- ///
- /// This is similar to the socket option `SO_PEERCRED`, but requires a
- /// process to explicitly send its credentials. A process running as root is
- /// allowed to specify any credentials, while credentials sent by other
- /// processes are verified by the kernel.
- ///
- /// For further information, please refer to the
- /// [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html) man page.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ScmCredentials(&'a UnixCredentials),
- /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
- /// a process connected to the socket.
- ///
- /// This is similar to the socket options `LOCAL_CREDS` and `LOCAL_PEERCRED`, but
- /// requires a process to explicitly send its credentials.
- ///
- /// Credentials are always overwritten by the kernel, so this variant does have
- /// any data, unlike the receive-side
- /// [`ControlMessageOwned::ScmCreds`].
- ///
- /// For further information, please refer to the
- /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ScmCreds,
-
- /// Set IV for `AF_ALG` crypto API.
- ///
- /// For further information, please refer to the
- /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- AlgSetIv(&'a [u8]),
- /// Set crypto operation for `AF_ALG` crypto API. It may be one of
- /// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
- ///
- /// For further information, please refer to the
- /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- AlgSetOp(&'a libc::c_int),
- /// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
- /// for `AF_ALG` crypto API.
- ///
- /// For further information, please refer to the
- /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
- #[cfg(any(
- target_os = "android",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- AlgSetAeadAssoclen(&'a u32),
-
- /// UDP GSO makes it possible for applications to generate network packets
- /// for a virtual MTU much greater than the real one.
- /// The length of the send data no longer matches the expected length on
- /// the wire.
- /// The size of the datagram payload as it should appear on the wire may be
- /// passed through this control message.
- /// Send buffer should consist of multiple fixed-size wire payloads
- /// following one by one, and the last, possibly smaller one.
- #[cfg(target_os = "linux")]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- UdpGsoSegments(&'a u16),
-
- /// Configure the sending addressing and interface for v4
- ///
- /// For further information, please refer to the
- /// [`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",
- target_os = "android",
- target_os = "ios",))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv4PacketInfo(&'a libc::in_pktinfo),
-
- /// Configure the sending addressing and interface for v6
- ///
- /// For further information, please refer to the
- /// [`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",
- target_os = "freebsd",
- target_os = "android",
- target_os = "ios",))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv6PacketInfo(&'a libc::in6_pktinfo),
-
- /// Configure the IPv4 source address with `IP_SENDSRCADDR`.
- #[cfg(any(
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "dragonfly",
- ))]
- #[cfg(feature = "net")]
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- Ipv4SendSrcAddr(&'a libc::in_addr),
-
- /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
- /// ancilliary msg (cmsg) should be attached to recieved
- /// skbs indicating the number of packets dropped by the
- /// socket between the last recieved packet and this
- /// received packet.
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- RxqOvfl(&'a u32),
-
- /// Configure the transmission time of packets.
- ///
- /// For further information, please refer to the
- /// [`tc-etf(8)`](https://man7.org/linux/man-pages/man8/tc-etf.8.html) man
- /// page.
- #[cfg(target_os = "linux")]
- TxTime(&'a u64),
-}
-
-// An opaque structure used to prevent cmsghdr from being a public type
-#[doc(hidden)]
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct UnknownCmsg(cmsghdr, Vec<u8>);
-
-impl<'a> ControlMessage<'a> {
- /// The value of CMSG_SPACE on this message.
- /// Safe because CMSG_SPACE is always safe
- fn space(&self) -> usize {
- unsafe{CMSG_SPACE(self.len() as libc::c_uint) as usize}
- }
-
- /// The value of CMSG_LEN on this message.
- /// Safe because CMSG_LEN is always safe
- #[cfg(any(target_os = "android",
- all(target_os = "linux", not(target_env = "musl"))))]
- fn cmsg_len(&self) -> usize {
- unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize}
- }
-
- #[cfg(not(any(target_os = "android",
- all(target_os = "linux", not(target_env = "musl")))))]
- fn cmsg_len(&self) -> libc::c_uint {
- unsafe{CMSG_LEN(self.len() as libc::c_uint)}
- }
-
- /// Return a reference to the payload data as a byte pointer
- fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
- let data_ptr = match *self {
- ControlMessage::ScmRights(fds) => {
- fds as *const _ as *const u8
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::ScmCredentials(creds) => {
- &creds.0 as *const libc::ucred as *const u8
- }
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ControlMessage::ScmCreds => {
- // The kernel overwrites the data, we just zero it
- // to make sure it's not uninitialized memory
- unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
- return
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetIv(iv) => {
- #[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
- let af_alg_iv = libc::af_alg_iv {
- ivlen: iv.len() as u32,
- iv: [0u8; 0],
- };
-
- let size = mem::size_of_val(&af_alg_iv);
-
- unsafe {
- ptr::copy_nonoverlapping(
- &af_alg_iv as *const _ as *const u8,
- cmsg_data,
- size,
- );
- ptr::copy_nonoverlapping(
- iv.as_ptr(),
- cmsg_data.add(size),
- iv.len()
- );
- };
-
- return
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetOp(op) => {
- op as *const _ as *const u8
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetAeadAssoclen(len) => {
- len as *const _ as *const u8
- },
- #[cfg(target_os = "linux")]
- #[cfg(feature = "net")]
- ControlMessage::UdpGsoSegments(gso_size) => {
- gso_size as *const _ as *const u8
- },
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv4SendSrcAddr(addr) => addr as *const _ as *const u8,
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- ControlMessage::RxqOvfl(drop_count) => {
- drop_count as *const _ as *const u8
- },
- #[cfg(target_os = "linux")]
- ControlMessage::TxTime(tx_time) => {
- tx_time as *const _ as *const u8
- },
- };
- unsafe {
- ptr::copy_nonoverlapping(
- data_ptr,
- cmsg_data,
- self.len()
- )
- };
- }
-
- /// The size of the payload, excluding its cmsghdr
- fn len(&self) -> usize {
- match *self {
- ControlMessage::ScmRights(fds) => {
- mem::size_of_val(fds)
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::ScmCredentials(creds) => {
- mem::size_of_val(creds)
- }
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ControlMessage::ScmCreds => {
- mem::size_of::<libc::cmsgcred>()
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetIv(iv) => {
- mem::size_of::<&[u8]>() + iv.len()
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetOp(op) => {
- mem::size_of_val(op)
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetAeadAssoclen(len) => {
- mem::size_of_val(len)
- },
- #[cfg(target_os = "linux")]
- #[cfg(feature = "net")]
- ControlMessage::UdpGsoSegments(gso_size) => {
- mem::size_of_val(gso_size)
- },
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info),
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv4SendSrcAddr(addr) => mem::size_of_val(addr),
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- ControlMessage::RxqOvfl(drop_count) => {
- mem::size_of_val(drop_count)
- },
- #[cfg(target_os = "linux")]
- ControlMessage::TxTime(tx_time) => {
- mem::size_of_val(tx_time)
- },
- }
- }
-
- /// Returns the value to put into the `cmsg_level` field of the header.
- fn cmsg_level(&self) -> libc::c_int {
- match *self {
- ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ControlMessage::ScmCreds => libc::SOL_SOCKET,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
- ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
- #[cfg(target_os = "linux")]
- #[cfg(feature = "net")]
- ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv4SendSrcAddr(_) => libc::IPPROTO_IP,
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
- #[cfg(target_os = "linux")]
- ControlMessage::TxTime(_) => libc::SOL_SOCKET,
- }
- }
-
- /// Returns the value to put into the `cmsg_type` field of the header.
- fn cmsg_type(&self) -> libc::c_int {
- match *self {
- ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- ControlMessage::ScmCreds => libc::SCM_CREDS,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetIv(_) => {
- libc::ALG_SET_IV
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetOp(_) => {
- libc::ALG_SET_OP
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- ControlMessage::AlgSetAeadAssoclen(_) => {
- libc::ALG_SET_AEAD_ASSOCLEN
- },
- #[cfg(target_os = "linux")]
- #[cfg(feature = "net")]
- ControlMessage::UdpGsoSegments(_) => {
- libc::UDP_SEGMENT
- },
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "android",
- target_os = "ios",))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
- #[cfg(any(target_os = "linux", target_os = "macos",
- target_os = "netbsd", target_os = "freebsd",
- target_os = "android", target_os = "ios",))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
- #[cfg(any(target_os = "netbsd", target_os = "freebsd",
- target_os = "openbsd", target_os = "dragonfly"))]
- #[cfg(feature = "net")]
- ControlMessage::Ipv4SendSrcAddr(_) => libc::IP_SENDSRCADDR,
- #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
- ControlMessage::RxqOvfl(_) => {
- libc::SO_RXQ_OVFL
- },
- #[cfg(target_os = "linux")]
- ControlMessage::TxTime(_) => {
- libc::SCM_TXTIME
- },
- }
- }
-
- // Unsafe: cmsg must point to a valid cmsghdr with enough space to
- // encode self.
- unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
- (*cmsg).cmsg_level = self.cmsg_level();
- (*cmsg).cmsg_type = self.cmsg_type();
- (*cmsg).cmsg_len = self.cmsg_len();
- self.copy_to_cmsg_data(CMSG_DATA(cmsg));
- }
-}
-
-
-/// Send data in scatter-gather vectors to a socket, possibly accompanied
-/// by ancillary data. Optionally direct the message at the given address,
-/// as with sendto.
-///
-/// Allocates if cmsgs is nonempty.
-///
-/// # Examples
-/// When not directing to any specific address, use `()` for the generic type
-/// ```
-/// # use nix::sys::socket::*;
-/// # use nix::unistd::pipe;
-/// # use std::io::IoSlice;
-/// let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None,
-/// SockFlag::empty())
-/// .unwrap();
-/// let (r, w) = pipe().unwrap();
-///
-/// let iov = [IoSlice::new(b"hello")];
-/// let fds = [r];
-/// let cmsg = ControlMessage::ScmRights(&fds);
-/// sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap();
-/// ```
-/// When directing to a specific address, the generic type will be inferred.
-/// ```
-/// # use nix::sys::socket::*;
-/// # use nix::unistd::pipe;
-/// # 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 = [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: &[IoSlice<'_>], cmsgs: &[ControlMessage],
- flags: MsgFlags, addr: Option<&S>) -> Result<usize>
- where S: SockaddrLike
-{
- let capacity = cmsgs.iter().map(|c| c.space()).sum();
-
- // First size the buffer needed to hold the cmsgs. It must be zeroed,
- // because subsequent code will not clear the padding bytes.
- let mut cmsg_buffer = vec![0u8; capacity];
-
- let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], iov, cmsgs, addr);
-
- let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
-
- Errno::result(ret).map(|r| r as usize)
-}
-
-
-/// An extension of `sendmsg` that allows the caller to transmit multiple
-/// messages on a socket using a single system call. This has performance
-/// benefits for some applications.
-///
-/// Allocations are performed for cmsgs and to build `msghdr` buffer
-///
-/// # Arguments
-///
-/// * `fd`: Socket file descriptor
-/// * `data`: Struct that implements `IntoIterator` with `SendMmsgData` items
-/// * `flags`: Optional flags passed directly to the operating system.
-///
-/// # Returns
-/// `Vec` with numbers of sent bytes on each sent message.
-///
-/// # References
-/// [`sendmsg`](fn.sendmsg.html)
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-pub fn sendmmsg<'a, XS, AS, C, I, S>(
- fd: RawFd,
- data: &'a mut MultiHeaders<S>,
- slices: XS,
- // one address per group of slices
- addrs: AS,
- // shared across all the messages
- cmsgs: C,
- flags: MsgFlags
-) -> crate::Result<MultiResults<'a, S>>
- where
- XS: IntoIterator<Item = &'a I>,
- AS: AsRef<[Option<S>]>,
- I: AsRef<[IoSlice<'a>]> + 'a,
- C: AsRef<[ControlMessage<'a>]> + 'a,
- S: SockaddrLike + 'a
-{
-
- let mut count = 0;
-
-
- for (i, ((slice, addr), mmsghdr)) in slices.into_iter().zip(addrs.as_ref()).zip(data.items.iter_mut() ).enumerate() {
- let mut p = &mut mmsghdr.msg_hdr;
- p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
- p.msg_iovlen = slice.as_ref().len() as _;
-
- p.msg_namelen = addr.as_ref().map_or(0, S::len);
- p.msg_name = addr.as_ref().map_or(ptr::null(), S::as_ptr) as _;
-
- // Encode each cmsg. This must happen after initializing the header because
- // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
- // CMSG_FIRSTHDR is always safe
- let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(p) };
- for cmsg in cmsgs.as_ref() {
- assert_ne!(pmhdr, ptr::null_mut());
- // Safe because we know that pmhdr is valid, and we initialized it with
- // sufficient space
- unsafe { cmsg.encode_into(pmhdr) };
- // Safe because mhdr is valid
- pmhdr = unsafe { CMSG_NXTHDR(p, pmhdr) };
- }
-
- count = i+1;
- }
-
- let sent = Errno::result(unsafe {
- libc::sendmmsg(
- fd,
- data.items.as_mut_ptr(),
- count as _,
- flags.bits() as _
- )
- })? as usize;
-
- Ok(MultiResults {
- rmm: data,
- current_index: 0,
- received: sent
- })
-
-}
-
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-#[derive(Debug)]
-/// Preallocated structures needed for [`recvmmsg`] and [`sendmmsg`] functions
-pub struct MultiHeaders<S> {
- // preallocated boxed slice of mmsghdr
- items: Box<[libc::mmsghdr]>,
- addresses: Box<[mem::MaybeUninit<S>]>,
- // while we are not using it directly - this is used to store control messages
- // and we retain pointers to them inside items array
- #[allow(dead_code)]
- cmsg_buffers: Option<Box<[u8]>>,
- msg_controllen: usize,
-}
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-impl<S> MultiHeaders<S> {
- /// Preallocate structure used by [`recvmmsg`] and [`sendmmsg`] takes number of headers to preallocate
- ///
- /// `cmsg_buffer` should be created with [`cmsg_space!`] if needed
- pub fn preallocate(num_slices: usize, cmsg_buffer: Option<Vec<u8>>) -> Self
- where
- S: Copy + SockaddrLike,
- {
- // we will be storing pointers to addresses inside mhdr - convert it into boxed
- // slice so it can'be changed later by pushing anything into self.addresses
- let mut addresses = vec![std::mem::MaybeUninit::uninit(); num_slices].into_boxed_slice();
-
- let msg_controllen = cmsg_buffer.as_ref().map_or(0, |v| v.capacity());
-
- // we'll need a cmsg_buffer for each slice, we preallocate a vector and split
- // it into "slices" parts
- let cmsg_buffers =
- cmsg_buffer.map(|v| vec![0u8; v.capacity() * num_slices].into_boxed_slice());
-
- let items = addresses
- .iter_mut()
- .enumerate()
- .map(|(ix, address)| {
- let (ptr, cap) = match &cmsg_buffers {
- Some(v) => ((&v[ix * msg_controllen] as *const u8), msg_controllen),
- None => (std::ptr::null(), 0),
- };
- let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null(), 0, ptr, cap, address.as_mut_ptr()) };
- libc::mmsghdr {
- msg_hdr,
- msg_len: 0,
- }
- })
- .collect::<Vec<_>>();
-
- Self {
- items: items.into_boxed_slice(),
- addresses,
- cmsg_buffers,
- msg_controllen,
- }
- }
-}
-
-/// An extension of recvmsg that allows the caller to receive multiple messages from a socket using a single system call.
-///
-/// This has performance benefits for some applications.
-///
-/// This method performs no allocations.
-///
-/// Returns an iterator producing [`RecvMsg`], one per received messages. Each `RecvMsg` can produce
-/// iterators over [`IoSlice`] with [`iovs`][RecvMsg::iovs`] and
-/// `ControlMessageOwned` with [`cmsgs`][RecvMsg::cmsgs].
-///
-/// # Bugs (in underlying implementation, at least in Linux)
-/// The timeout argument does not work as intended. The timeout is checked only after the receipt
-/// of each datagram, so that if up to `vlen`-1 datagrams are received before the timeout expires,
-/// but then no further datagrams are received, the call will block forever.
-///
-/// If an error occurs after at least one message has been received, the call succeeds, and returns
-/// the number of messages received. The error code is expected to be returned on a subsequent
-/// call to recvmmsg(). In the current implementation, however, the error code can be
-/// overwritten in the meantime by an unrelated network event on a socket, for example an
-/// incoming ICMP packet.
-
-// On aarch64 linux using recvmmsg and trying to get hardware/kernel timestamps might not
-// always produce the desired results - see https://github.com/nix-rust/nix/pull/1744 for more
-// details
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-pub fn recvmmsg<'a, XS, S, I>(
- fd: RawFd,
- data: &'a mut MultiHeaders<S>,
- slices: XS,
- flags: MsgFlags,
- mut timeout: Option<crate::sys::time::TimeSpec>,
-) -> crate::Result<MultiResults<'a, S>>
-where
- XS: IntoIterator<Item = &'a I>,
- I: AsRef<[IoSliceMut<'a>]> + 'a,
-{
- let mut count = 0;
- for (i, (slice, mmsghdr)) in slices.into_iter().zip(data.items.iter_mut()).enumerate() {
- let mut p = &mut mmsghdr.msg_hdr;
- p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec;
- p.msg_iovlen = slice.as_ref().len() as _;
- count = i + 1;
- }
-
- let timeout_ptr = timeout
- .as_mut()
- .map_or_else(std::ptr::null_mut, |t| t as *mut _ as *mut libc::timespec);
-
- let received = Errno::result(unsafe {
- libc::recvmmsg(
- fd,
- data.items.as_mut_ptr(),
- count as _,
- flags.bits() as _,
- timeout_ptr,
- )
- })? as usize;
-
- Ok(MultiResults {
- rmm: data,
- current_index: 0,
- received,
- })
-}
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-#[derive(Debug)]
-/// Iterator over results of [`recvmmsg`]/[`sendmmsg`]
-///
-///
-pub struct MultiResults<'a, S> {
- // preallocated structures
- rmm: &'a MultiHeaders<S>,
- current_index: usize,
- received: usize,
-}
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
-))]
-impl<'a, S> Iterator for MultiResults<'a, S>
-where
- S: Copy + SockaddrLike,
-{
- type Item = RecvMsg<'a, 'a, S>;
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn next(&mut self) -> Option<Self::Item> {
- if self.current_index >= self.received {
- return None;
- }
- let mmsghdr = self.rmm.items[self.current_index];
-
- // as long as we are not reading past the index writen by recvmmsg - address
- // will be initialized
- let address = unsafe { self.rmm.addresses[self.current_index].assume_init() };
-
- self.current_index += 1;
- Some(unsafe {
- read_mhdr(
- mmsghdr.msg_hdr,
- mmsghdr.msg_len as isize,
- self.rmm.msg_controllen,
- address,
- )
- })
- }
-}
-
-impl<'a, S> RecvMsg<'_, 'a, S> {
- /// Iterate over the filled io slices pointed by this msghdr
- pub fn iovs(&self) -> IoSliceIterator<'a> {
- IoSliceIterator {
- index: 0,
- remaining: self.bytes,
- slices: unsafe {
- // safe for as long as mgdr is properly initialized and references are valid.
- // for multi messages API we initialize it with an empty
- // slice and replace with a concrete buffer
- // for single message API we hold a lifetime reference to ioslices
- std::slice::from_raw_parts(self.mhdr.msg_iov as *const _, self.mhdr.msg_iovlen as _)
- },
- }
- }
-}
-
-#[derive(Debug)]
-pub struct IoSliceIterator<'a> {
- index: usize,
- remaining: usize,
- slices: &'a [IoSlice<'a>],
-}
-
-impl<'a> Iterator for IoSliceIterator<'a> {
- type Item = &'a [u8];
-
- fn next(&mut self) -> Option<Self::Item> {
- if self.index >= self.slices.len() {
- return None;
- }
- let slice = &self.slices[self.index][..self.remaining.min(self.slices[self.index].len())];
- self.remaining -= slice.len();
- self.index += 1;
- if slice.is_empty() {
- return None;
- }
-
- Some(slice)
- }
-}
-
-// test contains both recvmmsg and timestaping which is linux only
-// there are existing tests for recvmmsg only in tests/
-#[cfg(target_os = "linux")]
-#[cfg(test)]
-mod test {
- use crate::sys::socket::{AddressFamily, ControlMessageOwned};
- use crate::*;
- use std::str::FromStr;
-
- #[cfg_attr(qemu, ignore)]
- #[test]
- fn test_recvmm2() -> crate::Result<()> {
- use crate::sys::socket::{
- sendmsg, setsockopt, socket, sockopt::Timestamping, MsgFlags, SockFlag, SockType,
- SockaddrIn, TimestampingFlag,
- };
- use std::io::{IoSlice, IoSliceMut};
-
- let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
-
- let ssock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- )?;
-
- let rsock = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::SOCK_NONBLOCK,
- None,
- )?;
-
- crate::sys::socket::bind(rsock, &sock_addr)?;
-
- setsockopt(rsock, Timestamping, &TimestampingFlag::all())?;
-
- let sbuf = (0..400).map(|i| i as u8).collect::<Vec<_>>();
-
- let mut recv_buf = vec![0; 1024];
-
- let mut recv_iovs = Vec::new();
- let mut pkt_iovs = Vec::new();
-
- for (ix, chunk) in recv_buf.chunks_mut(256).enumerate() {
- pkt_iovs.push(IoSliceMut::new(chunk));
- if ix % 2 == 1 {
- recv_iovs.push(pkt_iovs);
- pkt_iovs = Vec::new();
- }
- }
- drop(pkt_iovs);
-
- let flags = MsgFlags::empty();
- let iov1 = [IoSlice::new(&sbuf)];
-
- let cmsg = cmsg_space!(crate::sys::socket::Timestamps);
- sendmsg(ssock, &iov1, &[], flags, Some(&sock_addr)).unwrap();
-
- let mut data = super::MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg));
-
- let t = sys::time::TimeSpec::from_duration(std::time::Duration::from_secs(10));
-
- let recv = super::recvmmsg(rsock, &mut data, recv_iovs.iter(), flags, Some(t))?;
-
- for rmsg in recv {
- #[cfg(not(any(qemu, target_arch = "aarch64")))]
- let mut saw_time = false;
- let mut recvd = 0;
- for cmsg in rmsg.cmsgs() {
- if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg {
- let ts = timestamps.system;
-
- let sys_time =
- crate::time::clock_gettime(crate::time::ClockId::CLOCK_REALTIME)?;
- let diff = if ts > sys_time {
- ts - sys_time
- } else {
- sys_time - ts
- };
- assert!(std::time::Duration::from(diff).as_secs() < 60);
- #[cfg(not(any(qemu, target_arch = "aarch64")))]
- {
- saw_time = true;
- }
- }
- }
-
- #[cfg(not(any(qemu, target_arch = "aarch64")))]
- assert!(saw_time);
-
- for iov in rmsg.iovs() {
- recvd += iov.len();
- }
- assert_eq!(recvd, 400);
- }
-
- Ok(())
- }
-}
-unsafe fn read_mhdr<'a, 'i, S>(
- mhdr: msghdr,
- r: isize,
- msg_controllen: usize,
- address: S,
-) -> RecvMsg<'a, 'i, S>
- where S: SockaddrLike
-{
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- let cmsghdr = {
- if mhdr.msg_controllen > 0 {
- debug_assert!(!mhdr.msg_control.is_null());
- debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
- CMSG_FIRSTHDR(&mhdr as *const msghdr)
- } else {
- ptr::null()
- }.as_ref()
- };
-
- RecvMsg {
- bytes: r as usize,
- cmsghdr,
- address: Some(address),
- flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
- mhdr,
- iobufs: std::marker::PhantomData,
- }
-}
-
-/// Pack pointers to various structures into into msghdr
-///
-/// # Safety
-/// `iov_buffer` and `iov_buffer_len` must point to a slice
-/// of `IoSliceMut` and number of available elements or be a null pointer and 0
-///
-/// `cmsg_buffer` and `cmsg_capacity` must point to a byte buffer used
-/// to store control headers later or be a null pointer and 0 if control
-/// headers are not used
-///
-/// Buffers must remain valid for the whole lifetime of msghdr
-unsafe fn pack_mhdr_to_receive<S>(
- iov_buffer: *const IoSliceMut,
- iov_buffer_len: usize,
- cmsg_buffer: *const u8,
- cmsg_capacity: usize,
- address: *mut S,
-) -> msghdr
- where
- S: SockaddrLike
-{
- // Musl's msghdr has private fields, so this is the only way to
- // initialize it.
- let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
- let p = mhdr.as_mut_ptr();
- (*p).msg_name = (*address).as_mut_ptr() as *mut c_void;
- (*p).msg_namelen = S::size();
- (*p).msg_iov = iov_buffer as *mut iovec;
- (*p).msg_iovlen = iov_buffer_len as _;
- (*p).msg_control = cmsg_buffer as *mut c_void;
- (*p).msg_controllen = cmsg_capacity as _;
- (*p).msg_flags = 0;
- mhdr.assume_init()
-}
-
-fn pack_mhdr_to_send<'a, I, C, S>(
- cmsg_buffer: &mut [u8],
- iov: I,
- cmsgs: C,
- addr: Option<&S>
-) -> msghdr
- where
- I: AsRef<[IoSlice<'a>]>,
- C: AsRef<[ControlMessage<'a>]>,
- S: SockaddrLike + 'a
-{
- let capacity = cmsg_buffer.len();
-
- // The message header must be initialized before the individual cmsgs.
- let cmsg_ptr = if capacity > 0 {
- cmsg_buffer.as_ptr() as *mut c_void
- } else {
- ptr::null_mut()
- };
-
- let mhdr = unsafe {
- // Musl's msghdr has private fields, so this is the only way to
- // initialize it.
- let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
- let p = mhdr.as_mut_ptr();
- (*p).msg_name = addr.map(S::as_ptr).unwrap_or(ptr::null()) as *mut _;
- (*p).msg_namelen = addr.map(S::len).unwrap_or(0);
- // transmute iov into a mutable pointer. sendmsg doesn't really mutate
- // the buffer, but the standard says that it takes a mutable pointer
- (*p).msg_iov = iov.as_ref().as_ptr() as *mut _;
- (*p).msg_iovlen = iov.as_ref().len() as _;
- (*p).msg_control = cmsg_ptr;
- (*p).msg_controllen = capacity as _;
- (*p).msg_flags = 0;
- mhdr.assume_init()
- };
-
- // Encode each cmsg. This must happen after initializing the header because
- // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
- // CMSG_FIRSTHDR is always safe
- let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) };
- for cmsg in cmsgs.as_ref() {
- assert_ne!(pmhdr, ptr::null_mut());
- // Safe because we know that pmhdr is valid, and we initialized it with
- // sufficient space
- unsafe { cmsg.encode_into(pmhdr) };
- // Safe because mhdr is valid
- pmhdr = unsafe { CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr) };
- }
-
- mhdr
-}
-
-/// Receive message in scatter-gather vectors from a socket, and
-/// optionally receive ancillary data into the provided buffer.
-/// If no ancillary data is desired, use () as the type parameter.
-///
-/// # Arguments
-///
-/// * `fd`: Socket file descriptor
-/// * `iov`: Scatter-gather list of buffers to receive the message
-/// * `cmsg_buffer`: Space to receive ancillary data. Should be created by
-/// [`cmsg_space!`](../../macro.cmsg_space.html)
-/// * `flags`: Optional flags passed directly to the operating system.
-///
-/// # References
-/// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
-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, 'inner, S>>
- where S: SockaddrLike + 'a,
- 'inner: 'outer
-{
- let mut address = mem::MaybeUninit::uninit();
-
- let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
- .map(|v| (v.as_mut_ptr(), v.capacity()))
- .unwrap_or((ptr::null_mut(), 0));
- let mut mhdr = unsafe {
- pack_mhdr_to_receive(iov.as_ref().as_ptr(), iov.len(), msg_control, msg_controllen, address.as_mut_ptr())
- };
-
- let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
-
- let r = Errno::result(ret)?;
-
- Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init()) })
-}
-}
-
-/// Create an endpoint for communication
-///
-/// The `protocol` specifies a particular protocol to be used with the
-/// socket. Normally only a single protocol exists to support a
-/// particular socket type within a given protocol family, in which case
-/// protocol can be specified as `None`. However, it is possible that many
-/// protocols may exist, in which case a particular protocol must be
-/// specified in this manner.
-///
-/// [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,
- Some(p) => p as c_int,
- };
-
- // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
- // little easier to understand by separating it out. So we have to merge these bitfields
- // here.
- let mut ty = ty as c_int;
- ty |= flags.bits();
-
- let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
-
- Errno::result(res)
-}
-
-/// Create a pair of connected sockets
-///
-/// [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() {
- None => 0,
- Some(p) => p as c_int,
- };
-
- // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
- // little easier to understand by separating it out. So we have to merge these bitfields
- // here.
- let mut ty = ty as c_int;
- ty |= flags.bits();
-
- let mut fds = [-1, -1];
-
- let res = unsafe {
- libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr())
- };
- Errno::result(res)?;
-
- Ok((fds[0], fds[1]))
-}
-
-/// Listen for connections on a socket
-///
-/// [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) };
-
- Errno::result(res).map(drop)
-}
-
-/// Bind a name to a socket
-///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
-pub fn bind(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
- let res = unsafe { libc::bind(fd, addr.as_ptr(), addr.len()) };
-
- Errno::result(res).map(drop)
-}
-
-/// Accept a connection on a socket
-///
-/// [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()) };
-
- Errno::result(res)
-}
-
-/// Accept a connection on a socket
-///
-/// [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 = "dragonfly",
- target_os = "emscripten",
- target_os = "freebsd",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
-pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
- let res = unsafe {
- libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits())
- };
-
- Errno::result(res)
-}
-
-/// Initiate a connection on a socket
-///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
-pub fn connect(fd: RawFd, addr: &dyn SockaddrLike) -> Result<()> {
- let res = unsafe { libc::connect(fd, addr.as_ptr(), addr.len()) };
-
- Errno::result(res).map(drop)
-}
-
-/// Receive data from a connection-oriented socket. Returns the number of
-/// bytes read
-///
-/// [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(
- sockfd,
- buf.as_ptr() as *mut c_void,
- buf.len() as size_t,
- flags.bits(),
- );
-
- Errno::result(ret).map(|r| r as usize)
- }
-}
-
-/// Receive data from a connectionless or connection-oriented socket. Returns
-/// the number of bytes read and, for connectionless sockets, the socket
-/// address of the sender.
-///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
-pub fn recvfrom<T: SockaddrLike>(
- sockfd: RawFd,
- buf: &mut [u8],
-) -> Result<(usize, Option<T>)> {
- unsafe {
- let mut addr = mem::MaybeUninit::<T>::uninit();
- let mut len = mem::size_of_val(&addr) as socklen_t;
-
- let ret = Errno::result(libc::recvfrom(
- sockfd,
- buf.as_ptr() as *mut c_void,
- buf.len() as size_t,
- 0,
- addr.as_mut_ptr() as *mut libc::sockaddr,
- &mut len as *mut socklen_t,
- ))? as usize;
-
- Ok((
- ret,
- T::from_raw(
- addr.assume_init().as_ptr() as *const libc::sockaddr,
- Some(len),
- ),
- ))
- }
-}
-
-/// Send a message to a socket
-///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
-pub fn sendto(
- fd: RawFd,
- buf: &[u8],
- addr: &dyn SockaddrLike,
- flags: MsgFlags,
-) -> Result<usize> {
- let ret = unsafe {
- libc::sendto(
- fd,
- buf.as_ptr() as *const c_void,
- buf.len() as size_t,
- flags.bits(),
- addr.as_ptr(),
- addr.len(),
- )
- };
-
- Errno::result(ret).map(|r| r as usize)
-}
-
-/// Send data to a connection-oriented socket. Returns the number of bytes read
-///
-/// [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(),
- )
- };
-
- Errno::result(ret).map(|r| r as usize)
-}
-
-/*
- *
- * ===== Socket Options =====
- *
- */
-
-/// Represents a socket option that can be retrieved.
-pub trait GetSockOpt: Copy {
- type Val;
-
- /// Look up the value of this socket option on the given socket.
- fn get(&self, fd: RawFd) -> Result<Self::Val>;
-}
-
-/// Represents a socket option that can be set.
-pub trait SetSockOpt: Clone {
- type Val;
-
- /// Set the value of this socket option on the given socket.
- fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
-}
-
-/// Get the current value for the requested socket option
-///
-/// [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](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
-///
-/// # Examples
-///
-/// ```
-/// use nix::sys::socket::setsockopt;
-/// use nix::sys::socket::sockopt::KeepAlive;
-/// use std::net::TcpListener;
-/// use std::os::unix::io::AsRawFd;
-///
-/// let listener = TcpListener::bind("0.0.0.0:0").unwrap();
-/// let fd = listener.as_raw_fd();
-/// let res = setsockopt(fd, KeepAlive, &true);
-/// assert!(res.is_ok());
-/// ```
-pub fn setsockopt<O: SetSockOpt>(
- fd: RawFd,
- opt: O,
- val: &O::Val,
-) -> Result<()> {
- opt.set(fd, val)
-}
-
-/// Get the address of the peer connected to the socket `fd`.
-///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
-pub fn getpeername<T: SockaddrLike>(fd: RawFd) -> Result<T> {
- unsafe {
- let mut addr = mem::MaybeUninit::<T>::uninit();
- let mut len = T::size();
-
- let ret = libc::getpeername(
- fd,
- addr.as_mut_ptr() as *mut libc::sockaddr,
- &mut len,
- );
-
- Errno::result(ret)?;
-
- T::from_raw(addr.assume_init().as_ptr(), Some(len)).ok_or(Errno::EINVAL)
- }
-}
-
-/// Get the current address to which the socket `fd` is bound.
-///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
-pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> {
- unsafe {
- let mut addr = mem::MaybeUninit::<T>::uninit();
- let mut len = T::size();
-
- let ret = libc::getsockname(
- fd,
- addr.as_mut_ptr() as *mut libc::sockaddr,
- &mut len,
- );
-
- Errno::result(ret)?;
-
- T::from_raw(addr.assume_init().as_ptr(), Some(len)).ok_or(Errno::EINVAL)
- }
-}
-
-/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a
-/// certain size.
-///
-/// In C this would usually be done by casting. The `len` argument
-/// should be the number of bytes in the `sockaddr_storage` that are actually
-/// allocated and valid. It must be at least as large as all the useful parts
-/// of the structure. Note that in the case of a `sockaddr_un`, `len` need not
-/// include the terminating null.
-#[deprecated(
- since = "0.24.0",
- note = "use SockaddrLike or SockaddrStorage instead"
-)]
-#[allow(deprecated)]
-pub fn sockaddr_storage_to_addr(
- addr: &sockaddr_storage,
- len: usize,
-) -> Result<SockAddr> {
- assert!(len <= mem::size_of::<sockaddr_storage>());
- if len < mem::size_of_val(&addr.ss_family) {
- return Err(Errno::ENOTCONN);
- }
-
- match c_int::from(addr.ss_family) {
- #[cfg(feature = "net")]
- libc::AF_INET => {
- assert!(len >= mem::size_of::<sockaddr_in>());
- let sin = unsafe {
- *(addr as *const sockaddr_storage as *const sockaddr_in)
- };
- Ok(SockAddr::Inet(InetAddr::V4(sin)))
- }
- #[cfg(feature = "net")]
- libc::AF_INET6 => {
- assert!(len >= mem::size_of::<sockaddr_in6>());
- let sin6 = unsafe { *(addr as *const _ as *const sockaddr_in6) };
- Ok(SockAddr::Inet(InetAddr::V6(sin6)))
- }
- libc::AF_UNIX => unsafe {
- let sun = *(addr as *const _ as *const sockaddr_un);
- let sun_len = len.try_into().unwrap();
- Ok(SockAddr::Unix(UnixAddr::from_raw_parts(sun, sun_len)))
- },
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg(feature = "net")]
- libc::AF_PACKET => {
- use libc::sockaddr_ll;
- // Don't assert anything about the size.
- // 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
- let sll = unsafe { *(addr as *const _ as *const sockaddr_ll) };
- Ok(SockAddr::Link(LinkAddr(sll)))
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_NETLINK => {
- use libc::sockaddr_nl;
- let snl = unsafe { *(addr as *const _ as *const sockaddr_nl) };
- Ok(SockAddr::Netlink(NetlinkAddr(snl)))
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_ALG => {
- use libc::sockaddr_alg;
- let salg = unsafe { *(addr as *const _ as *const sockaddr_alg) };
- Ok(SockAddr::Alg(AlgAddr(salg)))
- }
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::AF_VSOCK => {
- use libc::sockaddr_vm;
- let svm = unsafe { *(addr as *const _ as *const sockaddr_vm) };
- Ok(SockAddr::Vsock(VsockAddr(svm)))
- }
- af => panic!("unexpected address family {}", af),
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum Shutdown {
- /// Further receptions will be disallowed.
- Read,
- /// Further transmissions will be disallowed.
- Write,
- /// Further receptions and transmissions will be disallowed.
- Both,
-}
-
-/// Shut down part of a full-duplex connection.
-///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
-pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
- unsafe {
- use libc::shutdown;
-
- let how = match how {
- Shutdown::Read => libc::SHUT_RD,
- Shutdown::Write => libc::SHUT_WR,
- Shutdown::Both => libc::SHUT_RDWR,
- };
-
- Errno::result(shutdown(df, how)).map(drop)
- }
-}
-
-#[cfg(test)]
-mod tests {
- #[test]
- fn can_use_cmsg_space() {
- let _ = cmsg_space!(u8);
- }
-}
diff --git a/vendor/nix/src/sys/socket/sockopt.rs b/vendor/nix/src/sys/socket/sockopt.rs
deleted file mode 100644
index 06e9ee456..000000000
--- a/vendor/nix/src/sys/socket/sockopt.rs
+++ /dev/null
@@ -1,1422 +0,0 @@
-//! Socket options as used by `setsockopt` and `getsockopt`.
-use super::{GetSockOpt, SetSockOpt};
-use crate::errno::Errno;
-use crate::sys::time::TimeVal;
-use crate::Result;
-use cfg_if::cfg_if;
-use libc::{self, c_int, c_void, socklen_t};
-use std::ffi::{OsStr, OsString};
-use std::{
- convert::TryFrom,
- mem::{self, MaybeUninit}
-};
-#[cfg(target_family = "unix")]
-use std::os::unix::ffi::OsStrExt;
-use std::os::unix::io::RawFd;
-
-// Constants
-// TCP_CA_NAME_MAX isn't defined in user space include files
-#[cfg(any(target_os = "freebsd", target_os = "linux"))]
-#[cfg(feature = "net")]
-const TCP_CA_NAME_MAX: usize = 16;
-
-/// Helper for implementing `SetSockOpt` for a given socket option. See
-/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
-///
-/// This macro aims to help implementing `SetSockOpt` for different socket options that accept
-/// different kinds of data to be used with `setsockopt`.
-///
-/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
-/// you are implementing represents a simple type.
-///
-/// # Arguments
-///
-/// * `$name:ident`: name of the type you want to implement `SetSockOpt` for.
-/// * `$level:expr` : socket layer, or a `protocol level`: could be *raw sockets*
-/// (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
-/// and more. Please refer to your system manual for more options. Will be passed as the second
-/// argument (`level`) to the `setsockopt` call.
-/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
-/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
-/// to the `setsockopt` call.
-/// * Type of the value that you are going to set.
-/// * Type that implements the `Set` trait for the type from the previous item (like `SetBool` for
-/// `bool`, `SetUsize` for `usize`, etc.).
-macro_rules! setsockopt_impl {
- ($name:ident, $level:expr, $flag:path, $ty:ty, $setter:ty) => {
- impl SetSockOpt for $name {
- type Val = $ty;
-
- fn set(&self, fd: RawFd, val: &$ty) -> Result<()> {
- unsafe {
- let setter: $setter = Set::new(val);
-
- let res = libc::setsockopt(
- fd,
- $level,
- $flag,
- setter.ffi_ptr(),
- setter.ffi_len(),
- );
- Errno::result(res).map(drop)
- }
- }
- }
- };
-}
-
-/// Helper for implementing `GetSockOpt` for a given socket option. See
-/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html).
-///
-/// This macro aims to help implementing `GetSockOpt` for different socket options that accept
-/// different kinds of data to be use with `getsockopt`.
-///
-/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
-/// you are implementing represents a simple type.
-///
-/// # Arguments
-///
-/// * Name of the type you want to implement `GetSockOpt` for.
-/// * Socket layer, or a `protocol level`: could be *raw sockets* (`lic::SOL_SOCKET`), *ip
-/// protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), and more. Please refer
-/// to your system manual for more options. Will be passed as the second argument (`level`) to
-/// the `getsockopt` call.
-/// * A flag to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
-/// `libc::SO_ORIGINAL_DST` and others. Will be passed as the third argument (`option_name`) to
-/// the `getsockopt` call.
-/// * Type of the value that you are going to get.
-/// * Type that implements the `Get` trait for the type from the previous item (`GetBool` for
-/// `bool`, `GetUsize` for `usize`, etc.).
-macro_rules! getsockopt_impl {
- ($name:ident, $level:expr, $flag:path, $ty:ty, $getter:ty) => {
- impl GetSockOpt for $name {
- type Val = $ty;
-
- fn get(&self, fd: RawFd) -> Result<$ty> {
- unsafe {
- let mut getter: $getter = Get::uninit();
-
- let res = libc::getsockopt(
- fd,
- $level,
- $flag,
- getter.ffi_ptr(),
- getter.ffi_len(),
- );
- Errno::result(res)?;
-
- match <$ty>::try_from(getter.assume_init()) {
- Err(_) => Err(Errno::EINVAL),
- Ok(r) => Ok(r)
- }
- }
- }
- }
- };
-}
-
-/// Helper to generate the sockopt accessors. See
-/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html) and
-/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
-///
-/// This macro aims to help implementing `GetSockOpt` and `SetSockOpt` for different socket options
-/// that accept different kinds of data to be use with `getsockopt` and `setsockopt` respectively.
-///
-/// Basically this macro wraps up the [`getsockopt_impl!`](macro.getsockopt_impl.html) and
-/// [`setsockopt_impl!`](macro.setsockopt_impl.html) macros.
-///
-/// # Arguments
-///
-/// * `GetOnly`, `SetOnly` or `Both`: whether you want to implement only getter, only setter or
-/// both of them.
-/// * `$name:ident`: name of type `GetSockOpt`/`SetSockOpt` will be implemented for.
-/// * `$level:expr` : socket layer, or a `protocol level`: could be *raw sockets*
-/// (`lic::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
-/// and more. Please refer to your system manual for more options. Will be passed as the second
-/// argument (`level`) to the `getsockopt`/`setsockopt` call.
-/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
-/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
-/// to the `setsockopt`/`getsockopt` call.
-/// * `$ty:ty`: type of the value that will be get/set.
-/// * `$getter:ty`: `Get` implementation; optional; only for `GetOnly` and `Both`.
-/// * `$setter:ty`: `Set` implementation; optional; only for `SetOnly` and `Both`.
-// Some targets don't use all rules.
-#[allow(unknown_lints)]
-#[allow(unused_macro_rules)]
-macro_rules! sockopt_impl {
- ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, bool) => {
- sockopt_impl!($(#[$attr])*
- $name, GetOnly, $level, $flag, bool, GetBool);
- };
-
- ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, u8) => {
- sockopt_impl!($(#[$attr])* $name, GetOnly, $level, $flag, u8, GetU8);
- };
-
- ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, usize) =>
- {
- sockopt_impl!($(#[$attr])*
- $name, GetOnly, $level, $flag, usize, GetUsize);
- };
-
- ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, bool) => {
- sockopt_impl!($(#[$attr])*
- $name, SetOnly, $level, $flag, bool, SetBool);
- };
-
- ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, u8) => {
- sockopt_impl!($(#[$attr])* $name, SetOnly, $level, $flag, u8, SetU8);
- };
-
- ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, usize) =>
- {
- sockopt_impl!($(#[$attr])*
- $name, SetOnly, $level, $flag, usize, SetUsize);
- };
-
- ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, bool) => {
- sockopt_impl!($(#[$attr])*
- $name, Both, $level, $flag, bool, GetBool, SetBool);
- };
-
- ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, u8) => {
- sockopt_impl!($(#[$attr])*
- $name, Both, $level, $flag, u8, GetU8, SetU8);
- };
-
- ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, usize) => {
- sockopt_impl!($(#[$attr])*
- $name, Both, $level, $flag, usize, GetUsize, SetUsize);
- };
-
- ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path,
- OsString<$array:ty>) =>
- {
- sockopt_impl!($(#[$attr])*
- $name, Both, $level, $flag, OsString, GetOsString<$array>,
- SetOsString);
- };
-
- /*
- * Matchers with generic getter types must be placed at the end, so
- * they'll only match _after_ specialized matchers fail
- */
- ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty) =>
- {
- sockopt_impl!($(#[$attr])*
- $name, GetOnly, $level, $flag, $ty, GetStruct<$ty>);
- };
-
- ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty,
- $getter:ty) =>
- {
- $(#[$attr])*
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct $name;
-
- getsockopt_impl!($name, $level, $flag, $ty, $getter);
- };
-
- ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty) =>
- {
- sockopt_impl!($(#[$attr])*
- $name, SetOnly, $level, $flag, $ty, SetStruct<$ty>);
- };
-
- ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty,
- $setter:ty) =>
- {
- $(#[$attr])*
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct $name;
-
- setsockopt_impl!($name, $level, $flag, $ty, $setter);
- };
-
- ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, $ty:ty,
- $getter:ty, $setter:ty) =>
- {
- $(#[$attr])*
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct $name;
-
- setsockopt_impl!($name, $level, $flag, $ty, $setter);
- getsockopt_impl!($name, $level, $flag, $ty, $getter);
- };
-
- ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, $ty:ty) => {
- sockopt_impl!($(#[$attr])*
- $name, Both, $level, $flag, $ty, GetStruct<$ty>,
- SetStruct<$ty>);
- };
-}
-
-/*
- *
- * ===== Define sockopts =====
- *
- */
-
-sockopt_impl!(
- /// Enables local address reuse
- ReuseAddr,
- Both,
- libc::SOL_SOCKET,
- libc::SO_REUSEADDR,
- bool
-);
-#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
-sockopt_impl!(
- /// Permits multiple AF_INET or AF_INET6 sockets to be bound to an
- /// identical socket address.
- ReusePort,
- Both,
- libc::SOL_SOCKET,
- libc::SO_REUSEPORT,
- bool
-);
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Under most circumstances, TCP sends data when it is presented; when
- /// outstanding data has not yet been acknowledged, it gathers small amounts
- /// of output to be sent in a single packet once an acknowledgement is
- /// received. For a small number of clients, such as window systems that
- /// send a stream of mouse events which receive no replies, this
- /// packetization may cause significant delays. The boolean option
- /// TCP_NODELAY defeats this algorithm.
- TcpNoDelay,
- Both,
- libc::IPPROTO_TCP,
- libc::TCP_NODELAY,
- bool
-);
-sockopt_impl!(
- /// When enabled, a close(2) or shutdown(2) will not return until all
- /// queued messages for the socket have been successfully sent or the
- /// linger timeout has been reached.
- Linger,
- Both,
- libc::SOL_SOCKET,
- libc::SO_LINGER,
- libc::linger
-);
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Join a multicast group
- IpAddMembership,
- SetOnly,
- libc::IPPROTO_IP,
- libc::IP_ADD_MEMBERSHIP,
- super::IpMembershipRequest
-);
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Leave a multicast group.
- IpDropMembership,
- SetOnly,
- libc::IPPROTO_IP,
- libc::IP_DROP_MEMBERSHIP,
- super::IpMembershipRequest
-);
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- #[cfg(feature = "net")]
- sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Join an IPv6 multicast group.
- Ipv6AddMembership, SetOnly, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::Ipv6MembershipRequest);
- #[cfg(feature = "net")]
- sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Leave an IPv6 multicast group.
- Ipv6DropMembership, SetOnly, 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 = "solaris"))] {
- #[cfg(feature = "net")]
- sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Join an IPv6 multicast group.
- Ipv6AddMembership, SetOnly, libc::IPPROTO_IPV6,
- libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest);
- #[cfg(feature = "net")]
- sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Leave an IPv6 multicast group.
- Ipv6DropMembership, SetOnly, libc::IPPROTO_IPV6,
- libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest);
- }
-}
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Set or read the time-to-live value of outgoing multicast packets for
- /// this socket.
- IpMulticastTtl,
- Both,
- libc::IPPROTO_IP,
- libc::IP_MULTICAST_TTL,
- u8
-);
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Set or read a boolean integer argument that determines whether sent
- /// multicast packets should be looped back to the local sockets.
- IpMulticastLoop,
- Both,
- libc::IPPROTO_IP,
- libc::IP_MULTICAST_LOOP,
- bool
-);
-#[cfg(target_os = "linux")]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Set the protocol-defined priority for all packets to be
- /// sent on this socket
- Priority,
- Both,
- libc::SOL_SOCKET,
- libc::SO_PRIORITY,
- libc::c_int
-);
-#[cfg(target_os = "linux")]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Set or receive the Type-Of-Service (TOS) field that is
- /// sent with every IP packet originating from this socket
- IpTos,
- Both,
- libc::IPPROTO_IP,
- libc::IP_TOS,
- libc::c_int
-);
-#[cfg(target_os = "linux")]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Traffic class associated with outgoing packets
- Ipv6TClass,
- Both,
- libc::IPPROTO_IPV6,
- libc::IPV6_TCLASS,
- libc::c_int
-);
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// If enabled, this boolean option allows binding to an IP address that
- /// is nonlocal or does not (yet) exist.
- IpFreebind,
- Both,
- libc::IPPROTO_IP,
- libc::IP_FREEBIND,
- bool
-);
-sockopt_impl!(
- /// Specify the receiving timeout until reporting an error.
- ReceiveTimeout,
- Both,
- libc::SOL_SOCKET,
- libc::SO_RCVTIMEO,
- TimeVal
-);
-sockopt_impl!(
- /// Specify the sending timeout until reporting an error.
- SendTimeout,
- Both,
- libc::SOL_SOCKET,
- libc::SO_SNDTIMEO,
- TimeVal
-);
-sockopt_impl!(
- /// Set or get the broadcast flag.
- Broadcast,
- Both,
- libc::SOL_SOCKET,
- libc::SO_BROADCAST,
- bool
-);
-sockopt_impl!(
- /// If this option is enabled, out-of-band data is directly placed into
- /// the receive data stream.
- OobInline,
- Both,
- libc::SOL_SOCKET,
- libc::SO_OOBINLINE,
- bool
-);
-sockopt_impl!(
- /// Get and clear the pending socket error.
- SocketError,
- GetOnly,
- libc::SOL_SOCKET,
- libc::SO_ERROR,
- i32
-);
-sockopt_impl!(
- /// Set or get the don't route flag.
- DontRoute,
- Both,
- libc::SOL_SOCKET,
- libc::SO_DONTROUTE,
- bool
-);
-sockopt_impl!(
- /// Enable sending of keep-alive messages on connection-oriented sockets.
- KeepAlive,
- Both,
- libc::SOL_SOCKET,
- libc::SO_KEEPALIVE,
- bool
-);
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"
-))]
-sockopt_impl!(
- /// Get the credentials of the peer process of a connected unix domain
- /// socket.
- LocalPeerCred,
- GetOnly,
- 0,
- libc::LOCAL_PEERCRED,
- super::XuCred
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
- /// Return the credentials of the foreign process connected to this socket.
- PeerCredentials,
- GetOnly,
- libc::SOL_SOCKET,
- libc::SO_PEERCRED,
- super::UnixCredentials
-);
-#[cfg(any(target_os = "ios", target_os = "macos"))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Specify the amount of time, in seconds, that the connection must be idle
- /// before keepalive probes (if enabled) are sent.
- TcpKeepAlive,
- Both,
- libc::IPPROTO_TCP,
- libc::TCP_KEEPALIVE,
- u32
-);
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux"
-))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// The time (in seconds) the connection needs to remain idle before TCP
- /// starts sending keepalive probes
- TcpKeepIdle,
- Both,
- libc::IPPROTO_TCP,
- libc::TCP_KEEPIDLE,
- u32
-);
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- sockopt_impl!(
- /// The maximum segment size for outgoing TCP packets.
- TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
- } else {
- sockopt_impl!(
- /// The maximum segment size for outgoing TCP packets.
- TcpMaxSeg, GetOnly, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
- }
-}
-#[cfg(not(any(target_os = "openbsd", target_os = "haiku")))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// The maximum number of keepalive probes TCP should send before
- /// dropping the connection.
- TcpKeepCount,
- Both,
- libc::IPPROTO_TCP,
- libc::TCP_KEEPCNT,
- u32
-);
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-sockopt_impl!(
- #[allow(missing_docs)]
- // Not documented by Linux!
- TcpRepair,
- Both,
- libc::IPPROTO_TCP,
- libc::TCP_REPAIR,
- u32
-);
-#[cfg(not(any(target_os = "openbsd", target_os = "haiku")))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// The time (in seconds) between individual keepalive probes.
- TcpKeepInterval,
- Both,
- libc::IPPROTO_TCP,
- libc::TCP_KEEPINTVL,
- u32
-);
-#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Specifies the maximum amount of time in milliseconds that transmitted
- /// data may remain unacknowledged before TCP will forcibly close the
- /// corresponding connection
- TcpUserTimeout,
- Both,
- libc::IPPROTO_TCP,
- libc::TCP_USER_TIMEOUT,
- u32
-);
-sockopt_impl!(
- /// Sets or gets the maximum socket receive buffer in bytes.
- RcvBuf,
- Both,
- libc::SOL_SOCKET,
- libc::SO_RCVBUF,
- usize
-);
-sockopt_impl!(
- /// Sets or gets the maximum socket send buffer in bytes.
- SndBuf,
- Both,
- libc::SOL_SOCKET,
- libc::SO_SNDBUF,
- usize
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
- /// Using this socket option, a privileged (`CAP_NET_ADMIN`) process can
- /// perform the same task as `SO_RCVBUF`, but the `rmem_max limit` can be
- /// overridden.
- RcvBufForce,
- SetOnly,
- libc::SOL_SOCKET,
- libc::SO_RCVBUFFORCE,
- usize
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
- /// Using this socket option, a privileged (`CAP_NET_ADMIN`) process can
- /// perform the same task as `SO_SNDBUF`, but the `wmem_max` limit can be
- /// overridden.
- SndBufForce,
- SetOnly,
- libc::SOL_SOCKET,
- libc::SO_SNDBUFFORCE,
- usize
-);
-sockopt_impl!(
- /// Gets the socket type as an integer.
- SockType,
- GetOnly,
- libc::SOL_SOCKET,
- libc::SO_TYPE,
- super::SockType,
- GetStruct<i32>
-);
-sockopt_impl!(
- /// Returns a value indicating whether or not this socket has been marked to
- /// accept connections with `listen(2)`.
- AcceptConn,
- GetOnly,
- libc::SOL_SOCKET,
- libc::SO_ACCEPTCONN,
- bool
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
- /// Bind this socket to a particular device like “eth0”.
- BindToDevice,
- Both,
- libc::SOL_SOCKET,
- libc::SO_BINDTODEVICE,
- OsString<[u8; libc::IFNAMSIZ]>
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- #[allow(missing_docs)]
- // Not documented by Linux!
- OriginalDst,
- GetOnly,
- libc::SOL_IP,
- libc::SO_ORIGINAL_DST,
- libc::sockaddr_in
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
- #[allow(missing_docs)]
- // Not documented by Linux!
- Ip6tOriginalDst,
- GetOnly,
- libc::SOL_IPV6,
- libc::IP6T_SO_ORIGINAL_DST,
- libc::sockaddr_in6
-);
-#[cfg(any(target_os = "linux"))]
-sockopt_impl!(
- /// Specifies exact type of timestamping information collected by the kernel
- /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
- Timestamping,
- Both,
- libc::SOL_SOCKET,
- libc::SO_TIMESTAMPING,
- super::TimestampingFlag
-);
-#[cfg(not(target_os = "haiku"))]
-sockopt_impl!(
- /// Enable or disable the receiving of the `SO_TIMESTAMP` control message.
- ReceiveTimestamp,
- Both,
- libc::SOL_SOCKET,
- libc::SO_TIMESTAMP,
- bool
-);
-#[cfg(all(target_os = "linux"))]
-sockopt_impl!(
- /// Enable or disable the receiving of the `SO_TIMESTAMPNS` control message.
- ReceiveTimestampns,
- Both,
- libc::SOL_SOCKET,
- libc::SO_TIMESTAMPNS,
- bool
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Setting this boolean option enables transparent proxying on this socket.
- IpTransparent,
- Both,
- libc::SOL_IP,
- libc::IP_TRANSPARENT,
- bool
-);
-#[cfg(target_os = "openbsd")]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Allows the socket to be bound to addresses which are not local to the
- /// machine, so it can be used to make a transparent proxy.
- BindAny,
- Both,
- libc::SOL_SOCKET,
- libc::SO_BINDANY,
- bool
-);
-#[cfg(target_os = "freebsd")]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Can `bind(2)` to any address, even one not bound to any available
- /// network interface in the system.
- BindAny,
- Both,
- libc::IPPROTO_IP,
- libc::IP_BINDANY,
- bool
-);
-#[cfg(target_os = "linux")]
-sockopt_impl!(
- /// Set the mark for each packet sent through this socket (similar to the
- /// netfilter MARK target but socket-based).
- Mark,
- Both,
- libc::SOL_SOCKET,
- libc::SO_MARK,
- u32
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
- /// Enable or disable the receiving of the `SCM_CREDENTIALS` control
- /// message.
- PassCred,
- Both,
- libc::SOL_SOCKET,
- libc::SO_PASSCRED,
- bool
-);
-#[cfg(any(target_os = "freebsd", target_os = "linux"))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// This option allows the caller to set the TCP congestion control
- /// algorithm to be used, on a per-socket basis.
- TcpCongestion,
- Both,
- libc::IPPROTO_TCP,
- libc::TCP_CONGESTION,
- OsString<[u8; TCP_CA_NAME_MAX]>
-);
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
-))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Pass an `IP_PKTINFO` ancillary message that contains a pktinfo
- /// structure that supplies some information about the incoming packet.
- Ipv4PacketInfo,
- Both,
- libc::IPPROTO_IP,
- libc::IP_PKTINFO,
- bool
-);
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// Set delivery of the `IPV6_PKTINFO` control message on incoming
- /// datagrams.
- Ipv6RecvPacketInfo,
- Both,
- libc::IPPROTO_IPV6,
- libc::IPV6_RECVPKTINFO,
- bool
-);
-#[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// The `recvmsg(2)` call returns a `struct sockaddr_dl` corresponding to
- /// the interface on which the packet was received.
- Ipv4RecvIf,
- Both,
- libc::IPPROTO_IP,
- libc::IP_RECVIF,
- bool
-);
-#[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// The `recvmsg(2)` call will return the destination IP address for a UDP
- /// datagram.
- Ipv4RecvDstAddr,
- Both,
- libc::IPPROTO_IP,
- libc::IP_RECVDSTADDR,
- bool
-);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// The `recvmsg(2)` call will return the destination IP address for a UDP
- /// datagram.
- Ipv4OrigDstAddr,
- Both,
- libc::IPPROTO_IP,
- libc::IP_ORIGDSTADDR,
- bool
-);
-#[cfg(target_os = "linux")]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- #[allow(missing_docs)]
- // Not documented by Linux!
- UdpGsoSegment,
- Both,
- libc::SOL_UDP,
- libc::UDP_SEGMENT,
- libc::c_int
-);
-#[cfg(target_os = "linux")]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- #[allow(missing_docs)]
- // Not documented by Linux!
- UdpGroSegment,
- Both,
- libc::IPPROTO_UDP,
- libc::UDP_GRO,
- bool
-);
-#[cfg(target_os = "linux")]
-sockopt_impl!(
- /// Configures the behavior of time-based transmission of packets, for use
- /// with the `TxTime` control message.
- TxTime,
- Both,
- libc::SOL_SOCKET,
- libc::SO_TXTIME,
- libc::sock_txtime
-);
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-sockopt_impl!(
- /// Indicates that an unsigned 32-bit value ancillary message (cmsg) should
- /// be attached to received skbs indicating the number of packets dropped by
- /// the socket since its creation.
- RxqOvfl,
- Both,
- libc::SOL_SOCKET,
- libc::SO_RXQ_OVFL,
- libc::c_int
-);
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// The socket is restricted to sending and receiving IPv6 packets only.
- Ipv6V6Only,
- Both,
- libc::IPPROTO_IPV6,
- libc::IPV6_V6ONLY,
- bool
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
- /// Enable extended reliable error message passing.
- Ipv4RecvErr,
- Both,
- libc::IPPROTO_IP,
- libc::IP_RECVERR,
- bool
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
- /// Control receiving of asynchronous error options.
- Ipv6RecvErr,
- Both,
- libc::IPPROTO_IPV6,
- libc::IPV6_RECVERR,
- bool
-);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
- /// Fetch the current system-estimated Path MTU.
- IpMtu,
- GetOnly,
- libc::IPPROTO_IP,
- libc::IP_MTU,
- libc::c_int
-);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
-sockopt_impl!(
- /// Set or retrieve the current time-to-live field that is used in every
- /// packet sent from this socket.
- Ipv4Ttl,
- Both,
- libc::IPPROTO_IP,
- libc::IP_TTL,
- libc::c_int
-);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
-sockopt_impl!(
- /// Set the unicast hop limit for the socket.
- Ipv6Ttl,
- Both,
- libc::IPPROTO_IPV6,
- libc::IPV6_UNICAST_HOPS,
- libc::c_int
-);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
-#[cfg(feature = "net")]
-sockopt_impl!(
- #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
- /// The `recvmsg(2)` call will return the destination IP address for a UDP
- /// datagram.
- Ipv6OrigDstAddr,
- Both,
- libc::IPPROTO_IPV6,
- libc::IPV6_ORIGDSTADDR,
- bool
-);
-#[cfg(any(target_os = "ios", target_os = "macos"))]
-sockopt_impl!(
- /// Set "don't fragment packet" flag on the IP packet.
- IpDontFrag,
- Both,
- libc::IPPROTO_IP,
- libc::IP_DONTFRAG,
- bool
-);
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
-))]
-sockopt_impl!(
- /// Set "don't fragment packet" flag on the IPv6 packet.
- Ipv6DontFrag,
- Both,
- libc::IPPROTO_IPV6,
- libc::IPV6_DONTFRAG,
- bool
-);
-
-#[allow(missing_docs)]
-// Not documented by Linux!
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[derive(Copy, Clone, Debug)]
-pub struct AlgSetAeadAuthSize;
-
-// ALG_SET_AEAD_AUTH_SIZE read the length from passed `option_len`
-// See https://elixir.bootlin.com/linux/v4.4/source/crypto/af_alg.c#L222
-#[cfg(any(target_os = "android", target_os = "linux"))]
-impl SetSockOpt for AlgSetAeadAuthSize {
- type Val = usize;
-
- fn set(&self, fd: RawFd, val: &usize) -> Result<()> {
- unsafe {
- let res = libc::setsockopt(
- fd,
- libc::SOL_ALG,
- libc::ALG_SET_AEAD_AUTHSIZE,
- ::std::ptr::null(),
- *val as libc::socklen_t,
- );
- Errno::result(res).map(drop)
- }
- }
-}
-
-#[allow(missing_docs)]
-// Not documented by Linux!
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[derive(Clone, Debug)]
-pub struct AlgSetKey<T>(::std::marker::PhantomData<T>);
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-impl<T> Default for AlgSetKey<T> {
- fn default() -> Self {
- AlgSetKey(Default::default())
- }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-impl<T> SetSockOpt for AlgSetKey<T>
-where
- T: AsRef<[u8]> + Clone,
-{
- type Val = T;
-
- fn set(&self, fd: RawFd, val: &T) -> Result<()> {
- unsafe {
- let res = libc::setsockopt(
- fd,
- libc::SOL_ALG,
- libc::ALG_SET_KEY,
- val.as_ref().as_ptr() as *const _,
- val.as_ref().len() as libc::socklen_t,
- );
- Errno::result(res).map(drop)
- }
- }
-}
-
-/*
- *
- * ===== Accessor helpers =====
- *
- */
-
-/// Helper trait that describes what is expected from a `GetSockOpt` getter.
-trait Get<T> {
- /// Returns an uninitialized value.
- fn uninit() -> Self;
- /// Returns a pointer to the stored value. This pointer will be passed to the system's
- /// `getsockopt` call (`man 3p getsockopt`, argument `option_value`).
- fn ffi_ptr(&mut self) -> *mut c_void;
- /// Returns length of the stored value. This pointer will be passed to the system's
- /// `getsockopt` call (`man 3p getsockopt`, argument `option_len`).
- fn ffi_len(&mut self) -> *mut socklen_t;
- /// Returns the hopefully initialized inner value.
- unsafe fn assume_init(self) -> T;
-}
-
-/// Helper trait that describes what is expected from a `SetSockOpt` setter.
-trait Set<'a, T> {
- /// Initialize the setter with a given value.
- fn new(val: &'a T) -> Self;
- /// Returns a pointer to the stored value. This pointer will be passed to the system's
- /// `setsockopt` call (`man 3p setsockopt`, argument `option_value`).
- fn ffi_ptr(&self) -> *const c_void;
- /// Returns length of the stored value. This pointer will be passed to the system's
- /// `setsockopt` call (`man 3p setsockopt`, argument `option_len`).
- fn ffi_len(&self) -> socklen_t;
-}
-
-/// Getter for an arbitrary `struct`.
-struct GetStruct<T> {
- len: socklen_t,
- val: MaybeUninit<T>,
-}
-
-impl<T> Get<T> for GetStruct<T> {
- fn uninit() -> Self {
- GetStruct {
- len: mem::size_of::<T>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> T {
- assert_eq!(
- self.len as usize,
- mem::size_of::<T>(),
- "invalid getsockopt implementation"
- );
- self.val.assume_init()
- }
-}
-
-/// Setter for an arbitrary `struct`.
-struct SetStruct<'a, T: 'static> {
- ptr: &'a T,
-}
-
-impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
- fn new(ptr: &'a T) -> SetStruct<'a, T> {
- SetStruct { ptr }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- self.ptr as *const T as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- mem::size_of::<T>() as socklen_t
- }
-}
-
-/// Getter for a boolean value.
-struct GetBool {
- len: socklen_t,
- val: MaybeUninit<c_int>,
-}
-
-impl Get<bool> for GetBool {
- fn uninit() -> Self {
- GetBool {
- len: mem::size_of::<c_int>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> bool {
- assert_eq!(
- self.len as usize,
- mem::size_of::<c_int>(),
- "invalid getsockopt implementation"
- );
- self.val.assume_init() != 0
- }
-}
-
-/// Setter for a boolean value.
-struct SetBool {
- val: c_int,
-}
-
-impl<'a> Set<'a, bool> for SetBool {
- fn new(val: &'a bool) -> SetBool {
- SetBool {
- val: i32::from(*val),
- }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- &self.val as *const c_int as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- mem::size_of::<c_int>() as socklen_t
- }
-}
-
-/// Getter for an `u8` value.
-struct GetU8 {
- len: socklen_t,
- val: MaybeUninit<u8>,
-}
-
-impl Get<u8> for GetU8 {
- fn uninit() -> Self {
- GetU8 {
- len: mem::size_of::<u8>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> u8 {
- assert_eq!(
- self.len as usize,
- mem::size_of::<u8>(),
- "invalid getsockopt implementation"
- );
- self.val.assume_init()
- }
-}
-
-/// Setter for an `u8` value.
-struct SetU8 {
- val: u8,
-}
-
-impl<'a> Set<'a, u8> for SetU8 {
- fn new(val: &'a u8) -> SetU8 {
- SetU8 { val: *val }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- &self.val as *const u8 as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- mem::size_of::<c_int>() as socklen_t
- }
-}
-
-/// Getter for an `usize` value.
-struct GetUsize {
- len: socklen_t,
- val: MaybeUninit<c_int>,
-}
-
-impl Get<usize> for GetUsize {
- fn uninit() -> Self {
- GetUsize {
- len: mem::size_of::<c_int>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> usize {
- assert_eq!(
- self.len as usize,
- mem::size_of::<c_int>(),
- "invalid getsockopt implementation"
- );
- self.val.assume_init() as usize
- }
-}
-
-/// Setter for an `usize` value.
-struct SetUsize {
- val: c_int,
-}
-
-impl<'a> Set<'a, usize> for SetUsize {
- fn new(val: &'a usize) -> SetUsize {
- SetUsize { val: *val as c_int }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- &self.val as *const c_int as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- mem::size_of::<c_int>() as socklen_t
- }
-}
-
-/// Getter for a `OsString` value.
-struct GetOsString<T: AsMut<[u8]>> {
- len: socklen_t,
- val: MaybeUninit<T>,
-}
-
-impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
- fn uninit() -> Self {
- GetOsString {
- len: mem::size_of::<T>() as socklen_t,
- val: MaybeUninit::uninit(),
- }
- }
-
- fn ffi_ptr(&mut self) -> *mut c_void {
- self.val.as_mut_ptr() as *mut c_void
- }
-
- fn ffi_len(&mut self) -> *mut socklen_t {
- &mut self.len
- }
-
- unsafe fn assume_init(self) -> OsString {
- let len = self.len as usize;
- let mut v = self.val.assume_init();
- OsStr::from_bytes(&v.as_mut()[0..len]).to_owned()
- }
-}
-
-/// Setter for a `OsString` value.
-struct SetOsString<'a> {
- val: &'a OsStr,
-}
-
-impl<'a> Set<'a, OsString> for SetOsString<'a> {
- fn new(val: &'a OsString) -> SetOsString {
- SetOsString {
- val: val.as_os_str(),
- }
- }
-
- fn ffi_ptr(&self) -> *const c_void {
- self.val.as_bytes().as_ptr() as *const c_void
- }
-
- fn ffi_len(&self) -> socklen_t {
- self.val.len() as socklen_t
- }
-}
-
-#[cfg(test)]
-mod test {
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[test]
- fn can_get_peercred_on_unix_socket() {
- use super::super::*;
-
- let (a, b) = socketpair(
- AddressFamily::Unix,
- SockType::Stream,
- None,
- SockFlag::empty(),
- )
- .unwrap();
- let a_cred = getsockopt(a, super::PeerCredentials).unwrap();
- let b_cred = getsockopt(b, super::PeerCredentials).unwrap();
- assert_eq!(a_cred, b_cred);
- assert_ne!(a_cred.pid(), 0);
- }
-
- #[test]
- fn is_socket_type_unix() {
- use super::super::*;
- use crate::unistd::close;
-
- let (a, b) = socketpair(
- AddressFamily::Unix,
- SockType::Stream,
- None,
- SockFlag::empty(),
- )
- .unwrap();
- let a_type = getsockopt(a, super::SockType).unwrap();
- assert_eq!(a_type, SockType::Stream);
- close(a).unwrap();
- close(b).unwrap();
- }
-
- #[test]
- fn is_socket_type_dgram() {
- use super::super::*;
- use crate::unistd::close;
-
- let s = socket(
- AddressFamily::Inet,
- SockType::Datagram,
- SockFlag::empty(),
- None,
- )
- .unwrap();
- let s_type = getsockopt(s, super::SockType).unwrap();
- assert_eq!(s_type, SockType::Datagram);
- close(s).unwrap();
- }
-
- #[cfg(any(target_os = "freebsd", target_os = "linux"))]
- #[test]
- fn can_get_listen_on_tcp_socket() {
- use super::super::*;
- use crate::unistd::close;
-
- let s = socket(
- AddressFamily::Inet,
- SockType::Stream,
- SockFlag::empty(),
- None,
- )
- .unwrap();
- let s_listening = getsockopt(s, super::AcceptConn).unwrap();
- assert!(!s_listening);
- listen(s, 10).unwrap();
- let s_listening2 = getsockopt(s, super::AcceptConn).unwrap();
- assert!(s_listening2);
- close(s).unwrap();
- }
-}
diff --git a/vendor/nix/src/sys/stat.rs b/vendor/nix/src/sys/stat.rs
deleted file mode 100644
index 78203bfbe..000000000
--- a/vendor/nix/src/sys/stat.rs
+++ /dev/null
@@ -1,480 +0,0 @@
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))]
-pub use libc::c_uint;
-#[cfg(any(
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "dragonfly"
-))]
-pub use libc::c_ulong;
-pub use libc::stat as FileStat;
-pub use libc::{dev_t, mode_t};
-
-#[cfg(not(target_os = "redox"))]
-use crate::fcntl::{at_rawfd, AtFlags};
-use crate::sys::time::{TimeSpec, TimeVal};
-use crate::{errno::Errno, NixPath, Result};
-use std::mem;
-use std::os::unix::io::RawFd;
-
-libc_bitflags!(
- /// "File type" flags for `mknod` and related functions.
- pub struct SFlag: mode_t {
- S_IFIFO;
- S_IFCHR;
- S_IFDIR;
- S_IFBLK;
- S_IFREG;
- S_IFLNK;
- S_IFSOCK;
- S_IFMT;
- }
-);
-
-libc_bitflags! {
- /// "File mode / permissions" flags.
- pub struct Mode: mode_t {
- /// Read, write and execute for owner.
- S_IRWXU;
- /// Read for owner.
- S_IRUSR;
- /// Write for owner.
- S_IWUSR;
- /// Execute for owner.
- S_IXUSR;
- /// Read write and execute for group.
- S_IRWXG;
- /// Read fr group.
- S_IRGRP;
- /// Write for group.
- S_IWGRP;
- /// Execute for group.
- S_IXGRP;
- /// Read, write and execute for other.
- S_IRWXO;
- /// Read for other.
- S_IROTH;
- /// Write for other.
- S_IWOTH;
- /// Execute for other.
- S_IXOTH;
- /// Set user id on execution.
- S_ISUID as mode_t;
- /// Set group id on execution.
- S_ISGID as mode_t;
- S_ISVTX as mode_t;
- }
-}
-
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))]
-pub type type_of_file_flag = c_uint;
-#[cfg(any(
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "dragonfly"
-))]
-pub type type_of_file_flag = c_ulong;
-
-#[cfg(any(
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "macos",
- target_os = "ios"
-))]
-libc_bitflags! {
- /// File flags.
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub struct FileFlag: type_of_file_flag {
- /// The file may only be appended to.
- SF_APPEND;
- /// The file has been archived.
- SF_ARCHIVED;
- #[cfg(any(target_os = "dragonfly"))]
- SF_CACHE;
- /// The file may not be changed.
- SF_IMMUTABLE;
- /// Indicates a WAPBL journal file.
- #[cfg(any(target_os = "netbsd"))]
- SF_LOG;
- /// Do not retain history for file
- #[cfg(any(target_os = "dragonfly"))]
- SF_NOHISTORY;
- /// The file may not be renamed or deleted.
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- SF_NOUNLINK;
- /// Mask of superuser changeable flags
- SF_SETTABLE;
- /// Snapshot is invalid.
- #[cfg(any(target_os = "netbsd"))]
- SF_SNAPINVAL;
- /// The file is a snapshot file.
- #[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
- SF_SNAPSHOT;
- #[cfg(any(target_os = "dragonfly"))]
- SF_XLINK;
- /// The file may only be appended to.
- UF_APPEND;
- /// The file needs to be archived.
- #[cfg(any(target_os = "freebsd"))]
- UF_ARCHIVE;
- #[cfg(any(target_os = "dragonfly"))]
- UF_CACHE;
- /// File is compressed at the file system level.
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- UF_COMPRESSED;
- /// The file may be hidden from directory listings at the application's
- /// discretion.
- #[cfg(any(
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios",
- ))]
- UF_HIDDEN;
- /// The file may not be changed.
- UF_IMMUTABLE;
- /// Do not dump the file.
- UF_NODUMP;
- #[cfg(any(target_os = "dragonfly"))]
- UF_NOHISTORY;
- /// The file may not be renamed or deleted.
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
- UF_NOUNLINK;
- /// The file is offline, or has the Windows and CIFS
- /// `FILE_ATTRIBUTE_OFFLINE` attribute.
- #[cfg(any(target_os = "freebsd"))]
- UF_OFFLINE;
- /// The directory is opaque when viewed through a union stack.
- UF_OPAQUE;
- /// The file is read only, and may not be written or appended.
- #[cfg(any(target_os = "freebsd"))]
- UF_READONLY;
- /// The file contains a Windows reparse point.
- #[cfg(any(target_os = "freebsd"))]
- UF_REPARSE;
- /// Mask of owner changeable flags.
- UF_SETTABLE;
- /// The file has the Windows `FILE_ATTRIBUTE_SPARSE_FILE` attribute.
- #[cfg(any(target_os = "freebsd"))]
- UF_SPARSE;
- /// The file has the DOS, Windows and CIFS `FILE_ATTRIBUTE_SYSTEM`
- /// attribute.
- #[cfg(any(target_os = "freebsd"))]
- UF_SYSTEM;
- /// File renames and deletes are tracked.
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- UF_TRACKED;
- #[cfg(any(target_os = "dragonfly"))]
- UF_XLINK;
- }
-}
-
-/// Create a special or ordinary file, by pathname.
-pub fn mknod<P: ?Sized + NixPath>(
- path: &P,
- kind: SFlag,
- perm: Mode,
- dev: dev_t,
-) -> Result<()> {
- let res = path.with_nix_path(|cstr| unsafe {
- libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Create a special or ordinary file, relative to a given directory.
-#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "redox",
- target_os = "haiku"
-)))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn mknodat<P: ?Sized + NixPath>(
- dirfd: RawFd,
- path: &P,
- kind: SFlag,
- perm: Mode,
- dev: dev_t,
-) -> Result<()> {
- let res = path.with_nix_path(|cstr| unsafe {
- libc::mknodat(
- dirfd,
- cstr.as_ptr(),
- kind.bits | perm.bits() as mode_t,
- dev,
- )
- })?;
-
- Errno::result(res).map(drop)
-}
-
-#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub const fn major(dev: dev_t) -> u64 {
- ((dev >> 32) & 0xffff_f000) | ((dev >> 8) & 0x0000_0fff)
-}
-
-#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub const fn minor(dev: dev_t) -> u64 {
- ((dev >> 12) & 0xffff_ff00) | ((dev) & 0x0000_00ff)
-}
-
-#[cfg(target_os = "linux")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub const fn makedev(major: u64, minor: u64) -> dev_t {
- ((major & 0xffff_f000) << 32)
- | ((major & 0x0000_0fff) << 8)
- | ((minor & 0xffff_ff00) << 12)
- | (minor & 0x0000_00ff)
-}
-
-pub fn umask(mode: Mode) -> Mode {
- let prev = unsafe { libc::umask(mode.bits() as mode_t) };
- Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode")
-}
-
-pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
- let mut dst = mem::MaybeUninit::uninit();
- let res = path.with_nix_path(|cstr| unsafe {
- libc::stat(cstr.as_ptr(), dst.as_mut_ptr())
- })?;
-
- Errno::result(res)?;
-
- Ok(unsafe { dst.assume_init() })
-}
-
-pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
- let mut dst = mem::MaybeUninit::uninit();
- let res = path.with_nix_path(|cstr| unsafe {
- libc::lstat(cstr.as_ptr(), dst.as_mut_ptr())
- })?;
-
- Errno::result(res)?;
-
- Ok(unsafe { dst.assume_init() })
-}
-
-pub fn fstat(fd: RawFd) -> Result<FileStat> {
- let mut dst = mem::MaybeUninit::uninit();
- let res = unsafe { libc::fstat(fd, dst.as_mut_ptr()) };
-
- Errno::result(res)?;
-
- Ok(unsafe { dst.assume_init() })
-}
-
-#[cfg(not(target_os = "redox"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn fstatat<P: ?Sized + NixPath>(
- dirfd: RawFd,
- pathname: &P,
- f: AtFlags,
-) -> Result<FileStat> {
- let mut dst = mem::MaybeUninit::uninit();
- let res = pathname.with_nix_path(|cstr| unsafe {
- libc::fstatat(
- dirfd,
- cstr.as_ptr(),
- dst.as_mut_ptr(),
- f.bits() as libc::c_int,
- )
- })?;
-
- Errno::result(res)?;
-
- Ok(unsafe { dst.assume_init() })
-}
-
-/// Change the file permission bits of the file specified by a file descriptor.
-///
-/// # References
-///
-/// [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) };
-
- Errno::result(res).map(drop)
-}
-
-/// Flags for `fchmodat` function.
-#[derive(Clone, Copy, Debug)]
-pub enum FchmodatFlags {
- FollowSymlink,
- NoFollowSymlink,
-}
-
-/// Change the file permission bits.
-///
-/// The file to be changed is determined relative to the directory associated
-/// with the file descriptor `dirfd` or the current working directory
-/// if `dirfd` is `None`.
-///
-/// If `flag` is `FchmodatFlags::NoFollowSymlink` and `path` names a symbolic link,
-/// then the mode of the symbolic link is changed.
-///
-/// `fchmodat(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to
-/// a call `libc::chmod(path, mode)`. That's why `chmod` is unimplemented
-/// in the `nix` crate.
-///
-/// # References
-///
-/// [fchmodat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
-#[cfg(not(target_os = "redox"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn fchmodat<P: ?Sized + NixPath>(
- dirfd: Option<RawFd>,
- path: &P,
- mode: Mode,
- flag: FchmodatFlags,
-) -> Result<()> {
- let atflag = match flag {
- FchmodatFlags::FollowSymlink => AtFlags::empty(),
- FchmodatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
- };
- let res = path.with_nix_path(|cstr| unsafe {
- libc::fchmodat(
- at_rawfd(dirfd),
- cstr.as_ptr(),
- mode.bits() as mode_t,
- atflag.bits() as libc::c_int,
- )
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Change the access and modification times of a file.
-///
-/// `utimes(path, times)` is identical to
-/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)`. The former
-/// is a deprecated API so prefer using the latter if the platforms you care
-/// about support it.
-///
-/// # References
-///
-/// [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 {
- libc::utimes(cstr.as_ptr(), &times[0])
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Change the access and modification times of a file without following symlinks.
-///
-/// `lutimes(path, times)` is identical to
-/// `utimensat(None, path, times, UtimensatFlags::NoFollowSymlink)`. The former
-/// is a deprecated API so prefer using the latter if the platforms you care
-/// about support it.
-///
-/// # References
-///
-/// [lutimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
-#[cfg(any(
- target_os = "linux",
- target_os = "haiku",
- target_os = "ios",
- target_os = "macos",
- target_os = "freebsd",
- target_os = "netbsd"
-))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn lutimes<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 {
- libc::lutimes(cstr.as_ptr(), &times[0])
- })?;
-
- Errno::result(res).map(drop)
-}
-
-/// Change the access and modification times of the file specified by a file descriptor.
-///
-/// # References
-///
-/// [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()];
- let res = unsafe { libc::futimens(fd, &times[0]) };
-
- Errno::result(res).map(drop)
-}
-
-/// Flags for `utimensat` function.
-// TODO: replace with fcntl::AtFlags
-#[derive(Clone, Copy, Debug)]
-pub enum UtimensatFlags {
- FollowSymlink,
- NoFollowSymlink,
-}
-
-/// Change the access and modification times of a file.
-///
-/// The file to be changed is determined relative to the directory associated
-/// with the file descriptor `dirfd` or the current working directory
-/// if `dirfd` is `None`.
-///
-/// If `flag` is `UtimensatFlags::NoFollowSymlink` and `path` names a symbolic link,
-/// then the mode of the symbolic link is changed.
-///
-/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)` is identical to
-/// `utimes(path, times)`. The latter is a deprecated API so prefer using the
-/// former if the platforms you care about support it.
-///
-/// # References
-///
-/// [utimensat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
-#[cfg(not(target_os = "redox"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn utimensat<P: ?Sized + NixPath>(
- dirfd: Option<RawFd>,
- path: &P,
- atime: &TimeSpec,
- mtime: &TimeSpec,
- flag: UtimensatFlags,
-) -> Result<()> {
- let atflag = match flag {
- UtimensatFlags::FollowSymlink => AtFlags::empty(),
- UtimensatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
- };
- let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
- let res = path.with_nix_path(|cstr| unsafe {
- libc::utimensat(
- at_rawfd(dirfd),
- cstr.as_ptr(),
- &times[0],
- atflag.bits() as libc::c_int,
- )
- })?;
-
- Errno::result(res).map(drop)
-}
-
-#[cfg(not(target_os = "redox"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn mkdirat<P: ?Sized + NixPath>(
- fd: RawFd,
- path: &P,
- mode: Mode,
-) -> Result<()> {
- let res = path.with_nix_path(|cstr| unsafe {
- libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t)
- })?;
-
- Errno::result(res).map(drop)
-}
diff --git a/vendor/nix/src/sys/statfs.rs b/vendor/nix/src/sys/statfs.rs
deleted file mode 100644
index 9be8ca666..000000000
--- a/vendor/nix/src/sys/statfs.rs
+++ /dev/null
@@ -1,853 +0,0 @@
-//! Get filesystem statistics, non-portably
-//!
-//! See [`statvfs`](crate::sys::statvfs) for a portable alternative.
-#[cfg(not(any(target_os = "linux", target_os = "android")))]
-use std::ffi::CStr;
-use std::fmt::{self, Debug};
-use std::mem;
-use std::os::unix::io::AsRawFd;
-
-use cfg_if::cfg_if;
-
-#[cfg(all(
- feature = "mount",
- any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )
-))]
-use crate::mount::MntFlags;
-#[cfg(target_os = "linux")]
-use crate::sys::statvfs::FsFlags;
-use crate::{errno::Errno, NixPath, Result};
-
-/// Identifies a mounted file system
-#[cfg(target_os = "android")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub type fsid_t = libc::__fsid_t;
-/// Identifies a mounted file system
-#[cfg(not(target_os = "android"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub type fsid_t = libc::fsid_t;
-
-cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] {
- type type_of_statfs = libc::statfs64;
- const LIBC_FSTATFS: unsafe extern fn
- (fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int
- = libc::fstatfs64;
- const LIBC_STATFS: unsafe extern fn
- (path: *const libc::c_char, buf: *mut type_of_statfs) -> libc::c_int
- = libc::statfs64;
- } else {
- type type_of_statfs = libc::statfs;
- const LIBC_FSTATFS: unsafe extern fn
- (fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int
- = libc::fstatfs;
- const LIBC_STATFS: unsafe extern fn
- (path: *const libc::c_char, buf: *mut type_of_statfs) -> libc::c_int
- = libc::statfs;
- }
-}
-
-/// Describes a mounted file system
-#[derive(Clone, Copy)]
-#[repr(transparent)]
-pub struct Statfs(type_of_statfs);
-
-#[cfg(target_os = "freebsd")]
-type fs_type_t = u32;
-#[cfg(target_os = "android")]
-type fs_type_t = libc::c_ulong;
-#[cfg(all(target_os = "linux", target_arch = "s390x"))]
-type fs_type_t = libc::c_uint;
-#[cfg(all(target_os = "linux", target_env = "musl"))]
-type fs_type_t = libc::c_ulong;
-#[cfg(all(target_os = "linux", target_env = "uclibc"))]
-type fs_type_t = libc::c_int;
-#[cfg(all(
- target_os = "linux",
- not(any(
- target_arch = "s390x",
- target_env = "musl",
- target_env = "uclibc"
- ))
-))]
-type fs_type_t = libc::__fsword_t;
-
-/// Describes the file system type as known by the operating system.
-#[cfg(any(
- target_os = "freebsd",
- target_os = "android",
- all(target_os = "linux", target_arch = "s390x"),
- all(target_os = "linux", target_env = "musl"),
- all(
- target_os = "linux",
- not(any(target_arch = "s390x", target_env = "musl"))
- ),
-))]
-#[derive(Eq, Copy, Clone, PartialEq, Debug)]
-pub struct FsType(pub fs_type_t);
-
-// These constants are defined without documentation in the Linux headers, so we
-// can't very well document them here.
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const ADFS_SUPER_MAGIC: FsType =
- FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const AFFS_SUPER_MAGIC: FsType =
- FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const AFS_SUPER_MAGIC: FsType = FsType(libc::AFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const AUTOFS_SUPER_MAGIC: FsType =
- FsType(libc::AUTOFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const BPF_FS_MAGIC: FsType = FsType(libc::BPF_FS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const BTRFS_SUPER_MAGIC: FsType =
- FsType(libc::BTRFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const CGROUP2_SUPER_MAGIC: FsType =
- FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const CGROUP_SUPER_MAGIC: FsType =
- FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const CODA_SUPER_MAGIC: FsType =
- FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const DEBUGFS_MAGIC: FsType = FsType(libc::DEBUGFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const DEVPTS_SUPER_MAGIC: FsType =
- FsType(libc::DEVPTS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const ECRYPTFS_SUPER_MAGIC: FsType =
- FsType(libc::ECRYPTFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const EXT2_SUPER_MAGIC: FsType =
- FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const EXT3_SUPER_MAGIC: FsType =
- FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const EXT4_SUPER_MAGIC: FsType =
- FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const F2FS_SUPER_MAGIC: FsType =
- FsType(libc::F2FS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const FUSE_SUPER_MAGIC: FsType =
- FsType(libc::FUSE_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const FUTEXFS_SUPER_MAGIC: FsType =
- FsType(libc::FUTEXFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const HOSTFS_SUPER_MAGIC: FsType =
- FsType(libc::HOSTFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const HPFS_SUPER_MAGIC: FsType =
- FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const ISOFS_SUPER_MAGIC: FsType =
- FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const JFFS2_SUPER_MAGIC: FsType =
- FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const MINIX2_SUPER_MAGIC2: FsType =
- FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const MINIX2_SUPER_MAGIC: FsType =
- FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const MINIX3_SUPER_MAGIC: FsType =
- FsType(libc::MINIX3_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const MINIX_SUPER_MAGIC2: FsType =
- FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const MINIX_SUPER_MAGIC: FsType =
- FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const MSDOS_SUPER_MAGIC: FsType =
- FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const NILFS_SUPER_MAGIC: FsType =
- FsType(libc::NILFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const OCFS2_SUPER_MAGIC: FsType =
- FsType(libc::OCFS2_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const OPENPROM_SUPER_MAGIC: FsType =
- FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const OVERLAYFS_SUPER_MAGIC: FsType =
- FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const PROC_SUPER_MAGIC: FsType =
- FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const QNX4_SUPER_MAGIC: FsType =
- FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const QNX6_SUPER_MAGIC: FsType =
- FsType(libc::QNX6_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const RDTGROUP_SUPER_MAGIC: FsType =
- FsType(libc::RDTGROUP_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const REISERFS_SUPER_MAGIC: FsType =
- FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const SECURITYFS_MAGIC: FsType =
- FsType(libc::SECURITYFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const SELINUX_MAGIC: FsType = FsType(libc::SELINUX_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const SMACK_MAGIC: FsType = FsType(libc::SMACK_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const SYSFS_MAGIC: FsType = FsType(libc::SYSFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const TRACEFS_MAGIC: FsType = FsType(libc::TRACEFS_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const UDF_SUPER_MAGIC: FsType = FsType(libc::UDF_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const USBDEVICE_SUPER_MAGIC: FsType =
- FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const XENFS_SUPER_MAGIC: FsType =
- FsType(libc::XENFS_SUPER_MAGIC as fs_type_t);
-#[cfg(any(target_os = "linux", target_os = "android"))]
-#[allow(missing_docs)]
-pub const NSFS_MAGIC: FsType = FsType(libc::NSFS_MAGIC as fs_type_t);
-#[cfg(all(
- any(target_os = "linux", target_os = "android"),
- not(target_env = "musl")
-))]
-#[allow(missing_docs)]
-pub const XFS_SUPER_MAGIC: FsType = FsType(libc::XFS_SUPER_MAGIC as fs_type_t);
-
-impl Statfs {
- /// Magic code defining system type
- #[cfg(not(any(
- target_os = "openbsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos"
- )))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn filesystem_type(&self) -> FsType {
- FsType(self.0.f_type)
- }
-
- /// Magic code defining system type
- #[cfg(not(any(target_os = "linux", target_os = "android")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn filesystem_type_name(&self) -> &str {
- let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
- c_str.to_str().unwrap()
- }
-
- /// Optimal transfer block size
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn optimal_transfer_size(&self) -> i32 {
- self.0.f_iosize
- }
-
- /// Optimal transfer block size
- #[cfg(target_os = "openbsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn optimal_transfer_size(&self) -> u32 {
- self.0.f_iosize
- }
-
- /// Optimal transfer block size
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn optimal_transfer_size(&self) -> u32 {
- self.0.f_bsize
- }
-
- /// Optimal transfer block size
- #[cfg(any(
- target_os = "android",
- all(target_os = "linux", target_env = "musl")
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn optimal_transfer_size(&self) -> libc::c_ulong {
- self.0.f_bsize
- }
-
- /// Optimal transfer block size
- #[cfg(all(
- target_os = "linux",
- not(any(
- target_arch = "s390x",
- target_env = "musl",
- target_env = "uclibc"
- ))
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn optimal_transfer_size(&self) -> libc::__fsword_t {
- self.0.f_bsize
- }
-
- /// Optimal transfer block size
- #[cfg(all(target_os = "linux", target_env = "uclibc"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn optimal_transfer_size(&self) -> libc::c_int {
- self.0.f_bsize
- }
-
- /// Optimal transfer block size
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn optimal_transfer_size(&self) -> libc::c_long {
- self.0.f_iosize
- }
-
- /// Optimal transfer block size
- #[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn optimal_transfer_size(&self) -> u64 {
- self.0.f_iosize
- }
-
- /// Size of a block
- #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn block_size(&self) -> u32 {
- self.0.f_bsize
- }
-
- /// Size of a block
- // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn block_size(&self) -> u32 {
- self.0.f_bsize
- }
-
- /// Size of a block
- // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
- #[cfg(all(target_os = "linux", target_env = "musl"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn block_size(&self) -> libc::c_ulong {
- self.0.f_bsize
- }
-
- /// Size of a block
- // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
- #[cfg(all(target_os = "linux", target_env = "uclibc"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn block_size(&self) -> libc::c_int {
- self.0.f_bsize
- }
-
- /// Size of a block
- // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
- #[cfg(all(
- target_os = "linux",
- not(any(
- target_arch = "s390x",
- target_env = "musl",
- target_env = "uclibc"
- ))
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn block_size(&self) -> libc::__fsword_t {
- self.0.f_bsize
- }
-
- /// Size of a block
- #[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn block_size(&self) -> u64 {
- self.0.f_bsize
- }
-
- /// Size of a block
- #[cfg(target_os = "android")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn block_size(&self) -> libc::c_ulong {
- self.0.f_bsize
- }
-
- /// Size of a block
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn block_size(&self) -> libc::c_long {
- self.0.f_bsize
- }
-
- /// Get the mount flags
- #[cfg(all(
- feature = "mount",
- any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- #[allow(clippy::unnecessary_cast)] // Not unnecessary on all arches
- pub fn flags(&self) -> MntFlags {
- MntFlags::from_bits_truncate(self.0.f_flags as i32)
- }
-
- /// Get the mount flags
- // The f_flags field exists on Android and Fuchsia too, but without man
- // pages I can't tell if it can be cast to FsFlags.
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn flags(&self) -> FsFlags {
- FsFlags::from_bits_truncate(self.0.f_flags as libc::c_ulong)
- }
-
- /// Maximum length of filenames
- #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn maximum_name_length(&self) -> u32 {
- self.0.f_namemax
- }
-
- /// Maximum length of filenames
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn maximum_name_length(&self) -> u32 {
- self.0.f_namelen
- }
-
- /// Maximum length of filenames
- #[cfg(all(target_os = "linux", target_env = "musl"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn maximum_name_length(&self) -> libc::c_ulong {
- self.0.f_namelen
- }
-
- /// Maximum length of filenames
- #[cfg(all(target_os = "linux", target_env = "uclibc"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn maximum_name_length(&self) -> libc::c_int {
- self.0.f_namelen
- }
-
- /// Maximum length of filenames
- #[cfg(all(
- target_os = "linux",
- not(any(
- target_arch = "s390x",
- target_env = "musl",
- target_env = "uclibc"
- ))
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn maximum_name_length(&self) -> libc::__fsword_t {
- self.0.f_namelen
- }
-
- /// Maximum length of filenames
- #[cfg(target_os = "android")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn maximum_name_length(&self) -> libc::c_ulong {
- self.0.f_namelen
- }
-
- /// Total data blocks in filesystem
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "fuchsia",
- target_os = "openbsd",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks(&self) -> u64 {
- self.0.f_blocks
- }
-
- /// Total data blocks in filesystem
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks(&self) -> libc::c_long {
- self.0.f_blocks
- }
-
- /// Total data blocks in filesystem
- #[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks(&self) -> u32 {
- self.0.f_blocks
- }
-
- /// Free blocks in filesystem
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "fuchsia",
- target_os = "openbsd",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_free(&self) -> u64 {
- self.0.f_bfree
- }
-
- /// Free blocks in filesystem
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_free(&self) -> libc::c_long {
- self.0.f_bfree
- }
-
- /// Free blocks in filesystem
- #[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_free(&self) -> u32 {
- self.0.f_bfree
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "fuchsia",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_available(&self) -> u64 {
- self.0.f_bavail
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_available(&self) -> libc::c_long {
- self.0.f_bavail
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_available(&self) -> i64 {
- self.0.f_bavail
- }
-
- /// Free blocks available to unprivileged user
- #[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn blocks_available(&self) -> u32 {
- self.0.f_bavail
- }
-
- /// Total file nodes in filesystem
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "freebsd",
- target_os = "fuchsia",
- target_os = "openbsd",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files(&self) -> u64 {
- self.0.f_files
- }
-
- /// Total file nodes in filesystem
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files(&self) -> libc::c_long {
- self.0.f_files
- }
-
- /// Total file nodes in filesystem
- #[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files(&self) -> u32 {
- self.0.f_files
- }
-
- /// Free file nodes in filesystem
- #[cfg(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "android",
- target_os = "fuchsia",
- target_os = "openbsd",
- target_os = "linux",
- ))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files_free(&self) -> u64 {
- self.0.f_ffree
- }
-
- /// Free file nodes in filesystem
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files_free(&self) -> libc::c_long {
- self.0.f_ffree
- }
-
- /// Free file nodes in filesystem
- #[cfg(target_os = "freebsd")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files_free(&self) -> i64 {
- self.0.f_ffree
- }
-
- /// Free file nodes in filesystem
- #[cfg(target_os = "emscripten")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn files_free(&self) -> u32 {
- self.0.f_ffree
- }
-
- /// Filesystem ID
- pub fn filesystem_id(&self) -> fsid_t {
- self.0.f_fsid
- }
-}
-
-impl Debug for Statfs {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let mut ds = f.debug_struct("Statfs");
- ds.field("optimal_transfer_size", &self.optimal_transfer_size());
- ds.field("block_size", &self.block_size());
- ds.field("blocks", &self.blocks());
- ds.field("blocks_free", &self.blocks_free());
- ds.field("blocks_available", &self.blocks_available());
- ds.field("files", &self.files());
- ds.field("files_free", &self.files_free());
- ds.field("filesystem_id", &self.filesystem_id());
- #[cfg(all(
- feature = "mount",
- any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )
- ))]
- ds.field("flags", &self.flags());
- ds.finish()
- }
-}
-
-/// Describes a mounted file system.
-///
-/// The result is OS-dependent. For a portable alternative, see
-/// [`statvfs`](crate::sys::statvfs::statvfs).
-///
-/// # Arguments
-///
-/// `path` - Path to any file within the file system to describe
-pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
- unsafe {
- let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit();
- let res = path.with_nix_path(|path| {
- LIBC_STATFS(path.as_ptr(), stat.as_mut_ptr())
- })?;
- Errno::result(res).map(|_| Statfs(stat.assume_init()))
- }
-}
-
-/// Describes a mounted file system.
-///
-/// The result is OS-dependent. For a portable alternative, see
-/// [`fstatvfs`](crate::sys::statvfs::fstatvfs).
-///
-/// # Arguments
-///
-/// `fd` - File descriptor of any open file within the file system to describe
-pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
- unsafe {
- let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit();
- Errno::result(LIBC_FSTATFS(fd.as_raw_fd(), stat.as_mut_ptr()))
- .map(|_| Statfs(stat.assume_init()))
- }
-}
-
-#[cfg(test)]
-mod test {
- use std::fs::File;
-
- use crate::sys::statfs::*;
- use crate::sys::statvfs::*;
- use std::path::Path;
-
- #[test]
- fn statfs_call() {
- check_statfs("/tmp");
- check_statfs("/dev");
- check_statfs("/run");
- check_statfs("/");
- }
-
- #[test]
- fn fstatfs_call() {
- check_fstatfs("/tmp");
- check_fstatfs("/dev");
- check_fstatfs("/run");
- check_fstatfs("/");
- }
-
- fn check_fstatfs(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes()).unwrap();
- let file = File::open(path).unwrap();
- let fs = fstatfs(&file).unwrap();
- assert_fs_equals(fs, vfs);
- }
-
- fn check_statfs(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes()).unwrap();
- let fs = statfs(path.as_bytes()).unwrap();
- assert_fs_equals(fs, vfs);
- }
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
- assert_eq!(fs.files() as u64, vfs.files() as u64);
- assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
- assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
- }
-
- // This test is ignored because files_free/blocks_free can change after statvfs call and before
- // statfs call.
- #[test]
- #[ignore]
- fn statfs_call_strict() {
- check_statfs_strict("/tmp");
- check_statfs_strict("/dev");
- check_statfs_strict("/run");
- check_statfs_strict("/");
- }
-
- // This test is ignored because files_free/blocks_free can change after statvfs call and before
- // fstatfs call.
- #[test]
- #[ignore]
- fn fstatfs_call_strict() {
- check_fstatfs_strict("/tmp");
- check_fstatfs_strict("/dev");
- check_fstatfs_strict("/run");
- check_fstatfs_strict("/");
- }
-
- fn check_fstatfs_strict(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes());
- let file = File::open(path).unwrap();
- let fs = fstatfs(&file);
- assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
- }
-
- fn check_statfs_strict(path: &str) {
- if !Path::new(path).exists() {
- return;
- }
- let vfs = statvfs(path.as_bytes());
- let fs = statfs(path.as_bytes());
- assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
- }
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
- assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
- assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
- assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
- assert_eq!(fs.files() as u64, vfs.files() as u64);
- assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
- assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
- }
-}
diff --git a/vendor/nix/src/sys/statvfs.rs b/vendor/nix/src/sys/statvfs.rs
deleted file mode 100644
index 8de369f42..000000000
--- a/vendor/nix/src/sys/statvfs.rs
+++ /dev/null
@@ -1,173 +0,0 @@
-//! Get filesystem statistics
-//!
-//! 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;
-
-use libc::{self, c_ulong};
-
-use crate::{errno::Errno, NixPath, Result};
-
-#[cfg(not(target_os = "redox"))]
-libc_bitflags!(
- /// File system mount Flags
- #[repr(C)]
- #[derive(Default)]
- pub struct FsFlags: c_ulong {
- /// Read Only
- #[cfg(not(target_os = "haiku"))]
- ST_RDONLY;
- /// Do not allow the set-uid bits to have an effect
- #[cfg(not(target_os = "haiku"))]
- ST_NOSUID;
- /// Do not interpret character or block-special devices
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_NODEV;
- /// Do not allow execution of binaries on the filesystem
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_NOEXEC;
- /// All IO should be done synchronously
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_SYNCHRONOUS;
- /// Allow mandatory locks on the filesystem
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_MANDLOCK;
- /// Write on file/directory/symlink
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_WRITE;
- /// Append-only file
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_APPEND;
- /// Immutable file
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_IMMUTABLE;
- /// Do not update access times on files
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_NOATIME;
- /// Do not update access times on files
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_NODIRATIME;
- /// Update access time relative to modify/change time
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ST_RELATIME;
- }
-);
-
-/// Wrapper around the POSIX `statvfs` struct
-///
-/// 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);
-
-impl Statvfs {
- /// get the file system block size
- pub fn block_size(&self) -> c_ulong {
- self.0.f_bsize
- }
-
- /// Get the fundamental file system block size
- pub fn fragment_size(&self) -> c_ulong {
- self.0.f_frsize
- }
-
- /// Get the number of blocks.
- ///
- /// Units are in units of `fragment_size()`
- pub fn blocks(&self) -> libc::fsblkcnt_t {
- self.0.f_blocks
- }
-
- /// Get the number of free blocks in the file system
- pub fn blocks_free(&self) -> libc::fsblkcnt_t {
- self.0.f_bfree
- }
-
- /// Get the number of free blocks for unprivileged users
- pub fn blocks_available(&self) -> libc::fsblkcnt_t {
- self.0.f_bavail
- }
-
- /// Get the total number of file inodes
- pub fn files(&self) -> libc::fsfilcnt_t {
- self.0.f_files
- }
-
- /// Get the number of free file inodes
- pub fn files_free(&self) -> libc::fsfilcnt_t {
- self.0.f_ffree
- }
-
- /// Get the number of free file inodes for unprivileged users
- pub fn files_available(&self) -> libc::fsfilcnt_t {
- self.0.f_favail
- }
-
- /// Get the file system id
- pub fn filesystem_id(&self) -> c_ulong {
- self.0.f_fsid
- }
-
- /// Get the mount flags
- #[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- pub fn flags(&self) -> FsFlags {
- FsFlags::from_bits_truncate(self.0.f_flag)
- }
-
- /// Get the maximum filename length
- pub fn name_max(&self) -> c_ulong {
- self.0.f_namemax
- }
-}
-
-/// Return a `Statvfs` object with information about the `path`
-pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
- unsafe {
- Errno::clear();
- let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
- let res = path.with_nix_path(|path| {
- libc::statvfs(path.as_ptr(), stat.as_mut_ptr())
- })?;
-
- Errno::result(res).map(|_| Statvfs(stat.assume_init()))
- }
-}
-
-/// Return a `Statvfs` object with information about `fd`
-pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
- unsafe {
- Errno::clear();
- let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
- Errno::result(libc::fstatvfs(fd.as_raw_fd(), stat.as_mut_ptr()))
- .map(|_| Statvfs(stat.assume_init()))
- }
-}
-
-#[cfg(test)]
-mod test {
- use crate::sys::statvfs::*;
- use std::fs::File;
-
- #[test]
- fn statvfs_call() {
- statvfs(&b"/"[..]).unwrap();
- }
-
- #[test]
- fn fstatvfs_call() {
- let root = File::open("/").unwrap();
- fstatvfs(&root).unwrap();
- }
-}
diff --git a/vendor/nix/src/sys/sysinfo.rs b/vendor/nix/src/sys/sysinfo.rs
deleted file mode 100644
index e8aa00b00..000000000
--- a/vendor/nix/src/sys/sysinfo.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-use libc::{self, SI_LOAD_SHIFT};
-use std::time::Duration;
-use std::{cmp, mem};
-
-use crate::errno::Errno;
-use crate::Result;
-
-/// System info structure returned by `sysinfo`.
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-#[repr(transparent)]
-pub struct SysInfo(libc::sysinfo);
-
-// The fields are c_ulong on 32-bit linux, u64 on 64-bit linux; x32's ulong is u32
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
-type mem_blocks_t = u64;
-#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
-type mem_blocks_t = libc::c_ulong;
-
-impl SysInfo {
- /// Returns the load average tuple.
- ///
- /// The returned values represent the load average over time intervals of
- /// 1, 5, and 15 minutes, respectively.
- pub fn load_average(&self) -> (f64, f64, f64) {
- (
- self.0.loads[0] as f64 / (1 << SI_LOAD_SHIFT) as f64,
- self.0.loads[1] as f64 / (1 << SI_LOAD_SHIFT) as f64,
- self.0.loads[2] as f64 / (1 << SI_LOAD_SHIFT) as f64,
- )
- }
-
- /// Returns the time since system boot.
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- pub fn uptime(&self) -> Duration {
- // Truncate negative values to 0
- Duration::from_secs(cmp::max(self.0.uptime, 0) as u64)
- }
-
- /// Current number of processes.
- pub fn process_count(&self) -> u16 {
- self.0.procs
- }
-
- /// Returns the amount of swap memory in Bytes.
- pub fn swap_total(&self) -> u64 {
- self.scale_mem(self.0.totalswap)
- }
-
- /// Returns the amount of unused swap memory in Bytes.
- pub fn swap_free(&self) -> u64 {
- self.scale_mem(self.0.freeswap)
- }
-
- /// Returns the total amount of installed RAM in Bytes.
- pub fn ram_total(&self) -> u64 {
- self.scale_mem(self.0.totalram)
- }
-
- /// Returns the amount of completely unused RAM in Bytes.
- ///
- /// "Unused" in this context means that the RAM in neither actively used by
- /// programs, nor by the operating system as disk cache or buffer. It is
- /// "wasted" RAM since it currently serves no purpose.
- pub fn ram_unused(&self) -> u64 {
- self.scale_mem(self.0.freeram)
- }
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn scale_mem(&self, units: mem_blocks_t) -> u64 {
- units as u64 * self.0.mem_unit as u64
- }
-}
-
-/// Returns system information.
-///
-/// [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()) };
- Errno::result(res).map(|_| unsafe { SysInfo(info.assume_init()) })
-}
diff --git a/vendor/nix/src/sys/termios.rs b/vendor/nix/src/sys/termios.rs
deleted file mode 100644
index fba2cd826..000000000
--- a/vendor/nix/src/sys/termios.rs
+++ /dev/null
@@ -1,1227 +0,0 @@
-//! An interface for controlling asynchronous communication ports
-//!
-//! This interface provides a safe wrapper around the termios subsystem defined by POSIX. The
-//! underlying types are all implemented in libc for most platforms and either wrapped in safer
-//! types here or exported directly.
-//!
-//! If you are unfamiliar with the `termios` API, you should first read the
-//! [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.
-//! As this interface is not used with high-bandwidth information, this should be fine in most
-//! cases. The primary cost when using this API is that the `Termios` datatype here duplicates the
-//! standard fields of the underlying `termios` struct and uses safe type wrappers for those fields.
-//! This means that when crossing the FFI interface to the underlying C library, data is first
-//! copied into the underlying `termios` struct, then the operation is done, and the data is copied
-//! back (with additional sanity checking) into the safe wrapper types. The `termios` struct is
-//! relatively small across all platforms (on the order of 32-64 bytes).
-//!
-//! The following examples highlight some of the API use cases such that users coming from using C
-//! or reading the standard documentation will understand how to use the safe API exposed here.
-//!
-//! Example disabling processing of the end-of-file control character:
-//!
-//! ```
-//! # use self::nix::sys::termios::SpecialCharacterIndices::VEOF;
-//! # use self::nix::sys::termios::{_POSIX_VDISABLE, Termios};
-//! # let mut termios: Termios = unsafe { std::mem::zeroed() };
-//! termios.control_chars[VEOF as usize] = _POSIX_VDISABLE;
-//! ```
-//!
-//! The flags within `Termios` are defined as bitfields using the `bitflags` crate. This provides
-//! an interface for working with bitfields that is similar to working with the raw unsigned
-//! integer types but offers type safety because of the internal checking that values will always
-//! be a valid combination of the defined flags.
-//!
-//! An example showing some of the basic operations for interacting with the control flags:
-//!
-//! ```
-//! # use self::nix::sys::termios::{ControlFlags, Termios};
-//! # let mut termios: Termios = unsafe { std::mem::zeroed() };
-//! termios.control_flags & ControlFlags::CSIZE == ControlFlags::CS5;
-//! termios.control_flags |= ControlFlags::CS5;
-//! ```
-//!
-//! # Baud rates
-//!
-//! This API is not consistent across platforms when it comes to `BaudRate`: Android and Linux both
-//! only support the rates specified by the `BaudRate` enum through their termios API while the BSDs
-//! support arbitrary baud rates as the values of the `BaudRate` enum constants are the same integer
-//! value of the constant (`B9600` == `9600`). Therefore the `nix::termios` API uses the following
-//! conventions:
-//!
-//! * `cfgetispeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux
-//! * `cfgetospeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux
-//! * `cfsetispeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
-//! * `cfsetospeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
-//! * `cfsetspeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
-//!
-//! The most common use case of specifying a baud rate using the enum will work the same across
-//! platforms:
-//!
-//! ```rust
-//! # use nix::sys::termios::{BaudRate, cfsetispeed, cfsetospeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! cfsetispeed(&mut t, BaudRate::B9600).unwrap();
-//! cfsetospeed(&mut t, BaudRate::B9600).unwrap();
-//! cfsetspeed(&mut t, BaudRate::B9600).unwrap();
-//! # }
-//! ```
-//!
-//! Additionally round-tripping baud rates is consistent across platforms:
-//!
-//! ```rust
-//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetispeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! # cfsetspeed(&mut t, BaudRate::B9600).unwrap();
-//! let speed = cfgetispeed(&t);
-//! assert_eq!(speed, cfgetospeed(&t));
-//! cfsetispeed(&mut t, speed).unwrap();
-//! # }
-//! ```
-//!
-//! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`:
-//!
-#![cfg_attr(
- any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ),
- doc = " ```rust,ignore"
-)]
-#![cfg_attr(
- not(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )),
- doc = " ```rust"
-)]
-//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! # cfsetspeed(&mut t, BaudRate::B9600);
-//! assert_eq!(cfgetispeed(&t), BaudRate::B9600);
-//! assert_eq!(cfgetospeed(&t), BaudRate::B9600);
-//! # }
-//! ```
-//!
-//! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s:
-//!
-#![cfg_attr(
- any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ),
- doc = " ```rust"
-)]
-#![cfg_attr(
- not(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )),
- doc = " ```rust,ignore"
-)]
-//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! # cfsetspeed(&mut t, 9600u32);
-//! assert_eq!(cfgetispeed(&t), 9600u32);
-//! assert_eq!(cfgetospeed(&t), 9600u32);
-//! # }
-//! ```
-//!
-//! It's trivial to convert from a `BaudRate` to a `u32` on BSDs:
-//!
-#![cfg_attr(
- any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ),
- doc = " ```rust"
-)]
-#![cfg_attr(
- not(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )),
- doc = " ```rust,ignore"
-)]
-//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! # cfsetspeed(&mut t, 9600u32);
-//! assert_eq!(cfgetispeed(&t), BaudRate::B9600.into());
-//! assert_eq!(u32::from(BaudRate::B9600), 9600u32);
-//! # }
-//! ```
-//!
-//! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support)
-//! by specifying baud rates directly using `u32`s:
-//!
-#![cfg_attr(
- any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- ),
- doc = " ```rust"
-)]
-#![cfg_attr(
- not(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
- )),
- doc = " ```rust,ignore"
-)]
-//! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios};
-//! # fn main() {
-//! # let mut t: Termios = unsafe { std::mem::zeroed() };
-//! cfsetispeed(&mut t, 9600u32);
-//! cfsetospeed(&mut t, 9600u32);
-//! cfsetspeed(&mut t, 9600u32);
-//! # }
-//! ```
-use crate::errno::Errno;
-use crate::Result;
-use cfg_if::cfg_if;
-use libc::{self, c_int, tcflag_t};
-use std::cell::{Ref, RefCell};
-use std::convert::From;
-use std::mem;
-use std::os::unix::io::RawFd;
-
-#[cfg(feature = "process")]
-use crate::unistd::Pid;
-
-/// Stores settings for the termios API
-///
-/// This is a wrapper around the `libc::termios` struct that provides a safe interface for the
-/// standard fields. The only safe way to obtain an instance of this struct is to extract it from
-/// an open port using `tcgetattr()`.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Termios {
- inner: RefCell<libc::termios>,
- /// Input mode flags (see `termios.c_iflag` documentation)
- pub input_flags: InputFlags,
- /// Output mode flags (see `termios.c_oflag` documentation)
- pub output_flags: OutputFlags,
- /// Control mode flags (see `termios.c_cflag` documentation)
- pub control_flags: ControlFlags,
- /// Local mode flags (see `termios.c_lflag` documentation)
- pub local_flags: LocalFlags,
- /// Control characters (see `termios.c_cc` documentation)
- pub control_chars: [libc::cc_t; NCCS],
- /// Line discipline (see `termios.c_line` documentation)
- #[cfg(any(target_os = "linux", target_os = "android",))]
- pub line_discipline: libc::cc_t,
- /// Line discipline (see `termios.c_line` documentation)
- #[cfg(target_os = "haiku")]
- pub line_discipline: libc::c_char,
-}
-
-impl Termios {
- /// Exposes an immutable reference to the underlying `libc::termios` data structure.
- ///
- /// This is not part of `nix`'s public API because it requires additional work to maintain type
- /// safety.
- pub(crate) fn get_libc_termios(&self) -> Ref<libc::termios> {
- {
- let mut termios = self.inner.borrow_mut();
- termios.c_iflag = self.input_flags.bits();
- termios.c_oflag = self.output_flags.bits();
- termios.c_cflag = self.control_flags.bits();
- termios.c_lflag = self.local_flags.bits();
- termios.c_cc = self.control_chars;
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "haiku",
- ))]
- {
- termios.c_line = self.line_discipline;
- }
- }
- self.inner.borrow()
- }
-
- /// Exposes the inner `libc::termios` datastore within `Termios`.
- ///
- /// This is unsafe because if this is used to modify the inner `libc::termios` struct, it will
- /// not automatically update the safe wrapper type around it. In this case it should also be
- /// paired with a call to `update_wrapper()` so that the wrapper-type and internal
- /// representation stay consistent.
- pub(crate) unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios {
- {
- let mut termios = self.inner.borrow_mut();
- termios.c_iflag = self.input_flags.bits();
- termios.c_oflag = self.output_flags.bits();
- termios.c_cflag = self.control_flags.bits();
- termios.c_lflag = self.local_flags.bits();
- termios.c_cc = self.control_chars;
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "haiku",
- ))]
- {
- termios.c_line = self.line_discipline;
- }
- }
- self.inner.as_ptr()
- }
-
- /// Updates the wrapper values from the internal `libc::termios` data structure.
- pub(crate) fn update_wrapper(&mut self) {
- let termios = *self.inner.borrow_mut();
- self.input_flags = InputFlags::from_bits_truncate(termios.c_iflag);
- self.output_flags = OutputFlags::from_bits_truncate(termios.c_oflag);
- self.control_flags = ControlFlags::from_bits_truncate(termios.c_cflag);
- self.local_flags = LocalFlags::from_bits_truncate(termios.c_lflag);
- self.control_chars = termios.c_cc;
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "haiku",
- ))]
- {
- self.line_discipline = termios.c_line;
- }
- }
-}
-
-impl From<libc::termios> for Termios {
- fn from(termios: libc::termios) -> Self {
- Termios {
- inner: RefCell::new(termios),
- input_flags: InputFlags::from_bits_truncate(termios.c_iflag),
- output_flags: OutputFlags::from_bits_truncate(termios.c_oflag),
- control_flags: ControlFlags::from_bits_truncate(termios.c_cflag),
- local_flags: LocalFlags::from_bits_truncate(termios.c_lflag),
- control_chars: termios.c_cc,
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "haiku",
- ))]
- line_discipline: termios.c_line,
- }
- }
-}
-
-impl From<Termios> for libc::termios {
- fn from(termios: Termios) -> Self {
- termios.inner.into_inner()
- }
-}
-
-libc_enum! {
- /// Baud rates supported by the system.
- ///
- /// For the BSDs, arbitrary baud rates can be specified by using `u32`s directly instead of this
- /// enum.
- ///
- /// B0 is special and will disable the port.
- #[cfg_attr(all(any(target_os = "haiku"), target_pointer_width = "64"), repr(u8))]
- #[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))]
- #[cfg_attr(not(all(any(target_os = "ios", target_os = "macos", target_os = "haiku"), target_pointer_width = "64")), repr(u32))]
- #[non_exhaustive]
- pub enum BaudRate {
- B0,
- B50,
- B75,
- B110,
- B134,
- B150,
- B200,
- B300,
- B600,
- B1200,
- B1800,
- B2400,
- B4800,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B7200,
- B9600,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B14400,
- B19200,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B28800,
- B38400,
- B57600,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B76800,
- B115200,
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B153600,
- B230400,
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B307200,
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B460800,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B500000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B576000,
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B921600,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B1000000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B1152000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B1500000,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B2000000,
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B2500000,
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B3000000,
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B3500000,
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- B4000000,
- }
- impl TryFrom<libc::speed_t>
-}
-
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
-impl From<BaudRate> for u32 {
- fn from(b: BaudRate) -> u32 {
- b as u32
- }
-}
-
-#[cfg(target_os = "haiku")]
-impl From<BaudRate> for u8 {
- fn from(b: BaudRate) -> u8 {
- b as u8
- }
-}
-
-// TODO: Add TCSASOFT, which will require treating this as a bitfield.
-libc_enum! {
- /// Specify when a port configuration change should occur.
- ///
- /// Used as an argument to `tcsetattr()`
- #[repr(i32)]
- #[non_exhaustive]
- pub enum SetArg {
- /// The change will occur immediately
- TCSANOW,
- /// The change occurs after all output has been written
- TCSADRAIN,
- /// Same as `TCSADRAIN`, but will also flush the input buffer
- TCSAFLUSH,
- }
-}
-
-libc_enum! {
- /// Specify a combination of the input and output buffers to flush
- ///
- /// Used as an argument to `tcflush()`.
- #[repr(i32)]
- #[non_exhaustive]
- pub enum FlushArg {
- /// Flush data that was received but not read
- TCIFLUSH,
- /// Flush data written but not transmitted
- TCOFLUSH,
- /// Flush both received data not read and written data not transmitted
- TCIOFLUSH,
- }
-}
-
-libc_enum! {
- /// Specify how transmission flow should be altered
- ///
- /// Used as an argument to `tcflow()`.
- #[repr(i32)]
- #[non_exhaustive]
- pub enum FlowArg {
- /// Suspend transmission
- TCOOFF,
- /// Resume transmission
- TCOON,
- /// Transmit a STOP character, which should disable a connected terminal device
- TCIOFF,
- /// Transmit a START character, which should re-enable a connected terminal device
- TCION,
- }
-}
-
-// TODO: Make this usable directly as a slice index.
-#[cfg(not(target_os = "haiku"))]
-libc_enum! {
- /// Indices into the `termios.c_cc` array for special characters.
- #[repr(usize)]
- #[non_exhaustive]
- pub enum SpecialCharacterIndices {
- VDISCARD,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VDSUSP,
- VEOF,
- VEOL,
- VEOL2,
- VERASE,
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VERASE2,
- VINTR,
- VKILL,
- VLNEXT,
- #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
- target_os = "illumos", target_os = "solaris")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- 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 = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VSTATUS,
- VSTOP,
- VSUSP,
- #[cfg(target_os = "linux")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VSWTC,
- #[cfg(any(target_os = "haiku", target_os = "illumos", target_os = "solaris"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VSWTCH,
- #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
- target_os = "illumos", target_os = "solaris")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VTIME,
- VWERASE,
- #[cfg(target_os = "dragonfly")]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VCHECKPT,
- }
-}
-
-#[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;
-}
-
-pub use libc::NCCS;
-#[cfg(any(
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub use libc::_POSIX_VDISABLE;
-
-libc_bitflags! {
- /// Flags for configuring the input mode of a terminal
- pub struct InputFlags: tcflag_t {
- IGNBRK;
- BRKINT;
- IGNPAR;
- PARMRK;
- INPCK;
- ISTRIP;
- INLCR;
- IGNCR;
- ICRNL;
- IXON;
- IXOFF;
- #[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IXANY;
- #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IMAXBEL;
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- IUTF8;
- }
-}
-
-libc_bitflags! {
- /// Flags for configuring the output mode of a terminal
- pub struct OutputFlags: tcflag_t {
- OPOST;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "linux",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- OLCUC;
- ONLCR;
- OCRNL as tcflag_t;
- ONOCR as tcflag_t;
- ONLRET as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- OFILL as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- OFDEL as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NL0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NL1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CR0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CR1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CR2 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CR3 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- TAB0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- TAB1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- TAB2 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- TAB3 as tcflag_t;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- XTABS;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- BS0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- BS1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VT0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VT1 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- FF0 as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- FF1 as tcflag_t;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- OXTABS;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ONOEOT as tcflag_t;
-
- // Bitmasks for use with OutputFlags to select specific settings
- // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110
- // is resolved.
-
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NLDLY as tcflag_t; // FIXME: Datatype needs to be corrected in libc for mac
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CRDLY as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- TABDLY as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- BSDLY as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- VTDLY as tcflag_t;
- #[cfg(any(target_os = "android",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- FFDLY as tcflag_t;
- }
-}
-
-libc_bitflags! {
- /// Flags for setting the control mode of a terminal
- pub struct ControlFlags: tcflag_t {
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CIGNORE;
- CS5;
- CS6;
- CS7;
- CS8;
- CSTOPB;
- CREAD;
- PARENB;
- PARODD;
- HUPCL;
- CLOCAL;
- #[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CRTSCTS;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CBAUD;
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "mips"))))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CMSPAR;
- #[cfg(any(target_os = "android",
- all(target_os = "linux",
- not(any(target_arch = "powerpc", target_arch = "powerpc64")))))]
- CIBAUD;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CBAUDEX;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- MDMBUF;
- #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CHWFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CCTS_OFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CRTS_IFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CDTR_IFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CDSR_OFLOW;
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- CCAR_OFLOW;
-
- // Bitmasks for use with ControlFlags to select specific settings
- // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110
- // is resolved.
-
- CSIZE;
- }
-}
-
-libc_bitflags! {
- /// Flags for setting any local modes
- pub struct LocalFlags: tcflag_t {
- #[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ECHOKE;
- ECHOE;
- ECHOK;
- ECHO;
- ECHONL;
- #[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ECHOPRT;
- #[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ECHOCTL;
- ISIG;
- ICANON;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- ALTWERASE;
- IEXTEN;
- #[cfg(not(any(target_os = "redox", target_os = "haiku")))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- EXTPROC;
- TOSTOP;
- #[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- FLUSHO;
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- NOKERNINFO;
- #[cfg(not(target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PENDIN;
- NOFLSH;
- }
-}
-
-cfg_if! {
- if #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))] {
- /// Get input baud rate (see
- /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
- ///
- /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- pub fn cfgetispeed(termios: &Termios) -> u32 {
- let inner_termios = termios.get_libc_termios();
- unsafe { libc::cfgetispeed(&*inner_termios) as u32 }
- }
-
- /// Get output baud rate (see
- /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
- ///
- /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- pub fn cfgetospeed(termios: &Termios) -> u32 {
- let inner_termios = termios.get_libc_termios();
- unsafe { libc::cfgetospeed(&*inner_termios) as u32 }
- }
-
- /// Set input baud rate (see
- /// [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<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetispeed(inner_termios, baud.into() as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
-
- /// Set output baud rate (see
- /// [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<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetospeed(inner_termios, baud.into() as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
-
- /// Set both the input and output baud rates (see
- /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)).
- ///
- /// `cfsetspeed()` sets the input and output baud rate in the given termios structure. Note that
- /// this is part of the 4.4BSD standard and not part of POSIX.
- pub fn cfsetspeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetspeed(inner_termios, baud.into() as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
- } else {
- use std::convert::TryInto;
-
- /// Get input baud rate (see
- /// [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 {
- let inner_termios = termios.get_libc_termios();
- unsafe { libc::cfgetispeed(&*inner_termios) }.try_into().unwrap()
- }
-
- /// Get output baud rate (see
- /// [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 {
- let inner_termios = termios.get_libc_termios();
- unsafe { libc::cfgetospeed(&*inner_termios) }.try_into().unwrap()
- }
-
- /// Set input baud rate (see
- /// [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<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetispeed(inner_termios, baud as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
-
- /// Set output baud rate (see
- /// [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<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetospeed(inner_termios, baud as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
-
- /// Set both the input and output baud rates (see
- /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)).
- ///
- /// `cfsetspeed()` sets the input and output baud rate in the given `Termios` structure. Note that
- /// this is part of the 4.4BSD standard and not part of POSIX.
- #[cfg(not(target_os = "haiku"))]
- pub fn cfsetspeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- let res = unsafe { libc::cfsetspeed(inner_termios, baud as libc::speed_t) };
- termios.update_wrapper();
- Errno::result(res).map(drop)
- }
- }
-}
-
-/// Configures the port to something like the "raw" mode of the old Version 7 terminal driver (see
-/// [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
-/// that this is a non-standard function, but is available on Linux and BSDs.
-pub fn cfmakeraw(termios: &mut Termios) {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- unsafe {
- libc::cfmakeraw(inner_termios);
- }
- termios.update_wrapper();
-}
-
-/// Configures the port to "sane" mode (like the configuration of a newly created terminal) (see
-/// [tcsetattr(3)](https://www.freebsd.org/cgi/man.cgi?query=tcsetattr)).
-///
-/// Note that this is a non-standard function, available on FreeBSD.
-#[cfg(target_os = "freebsd")]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-pub fn cfmakesane(termios: &mut Termios) {
- let inner_termios = unsafe { termios.get_libc_termios_mut() };
- unsafe {
- libc::cfmakesane(inner_termios);
- }
- termios.update_wrapper();
-}
-
-/// Return the configuration of a port
-/// [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
-/// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`.
-pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
- let mut termios = mem::MaybeUninit::uninit();
-
- let res = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) };
-
- Errno::result(res)?;
-
- unsafe { Ok(termios.assume_init().into()) }
-}
-
-/// Set the configuration for a terminal (see
-/// [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
-/// *any* of the parameters were successfully set, not only if all were set successfully.
-pub fn tcsetattr(fd: RawFd, actions: SetArg, termios: &Termios) -> Result<()> {
- let inner_termios = termios.get_libc_termios();
- Errno::result(unsafe {
- libc::tcsetattr(fd, actions as c_int, &*inner_termios)
- })
- .map(drop)
-}
-
-/// Block until all output data is written (see
-/// [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)](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`.
-pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> {
- Errno::result(unsafe { libc::tcflow(fd, action as c_int) }).map(drop)
-}
-
-/// Discard data in the output or input queue (see
-/// [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`.
-pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> {
- Errno::result(unsafe { libc::tcflush(fd, action as c_int) }).map(drop)
-}
-
-/// Send a break for a specific duration (see
-/// [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.
-pub fn tcsendbreak(fd: RawFd, duration: c_int) -> Result<()> {
- Errno::result(unsafe { libc::tcsendbreak(fd, duration) }).map(drop)
-}
-
-feature! {
-#![feature = "process"]
-/// Get the session controlled by the given terminal (see
-/// [tcgetsid(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
-pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
- let res = unsafe { libc::tcgetsid(fd) };
-
- Errno::result(res).map(Pid::from_raw)
-}
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use std::convert::TryFrom;
-
- #[test]
- fn try_from() {
- assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0));
- #[cfg(not(target_os = "haiku"))]
- BaudRate::try_from(999999999).expect_err("assertion failed");
- #[cfg(target_os = "haiku")]
- BaudRate::try_from(99).expect_err("assertion failed");
- }
-}
diff --git a/vendor/nix/src/sys/time.rs b/vendor/nix/src/sys/time.rs
deleted file mode 100644
index 0042c4508..000000000
--- a/vendor/nix/src/sys/time.rs
+++ /dev/null
@@ -1,811 +0,0 @@
-#[cfg_attr(target_env = "musl", allow(deprecated))]
-// https://github.com/rust-lang/libc/issues/1848
-pub use libc::{suseconds_t, time_t};
-use libc::{timespec, timeval};
-use std::convert::From;
-use std::time::Duration;
-use std::{cmp, fmt, ops};
-
-const fn zero_init_timespec() -> timespec {
- // `std::mem::MaybeUninit::zeroed()` is not yet a const fn
- // (https://github.com/rust-lang/rust/issues/91850) so we will instead initialize an array of
- // the appropriate size to zero and then transmute it to a timespec value.
- unsafe { std::mem::transmute([0u8; std::mem::size_of::<timespec>()]) }
-}
-
-#[cfg(any(
- all(feature = "time", any(target_os = "android", target_os = "linux")),
- all(
- any(
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd"
- ),
- feature = "time",
- feature = "signal"
- )
-))]
-pub(crate) mod timer {
- use crate::sys::time::{zero_init_timespec, TimeSpec};
- use bitflags::bitflags;
-
- #[derive(Debug, Clone, Copy)]
- pub(crate) struct TimerSpec(libc::itimerspec);
-
- impl TimerSpec {
- pub const fn none() -> Self {
- Self(libc::itimerspec {
- it_interval: zero_init_timespec(),
- it_value: zero_init_timespec(),
- })
- }
- }
-
- impl AsMut<libc::itimerspec> for TimerSpec {
- fn as_mut(&mut self) -> &mut libc::itimerspec {
- &mut self.0
- }
- }
-
- impl AsRef<libc::itimerspec> for TimerSpec {
- fn as_ref(&self) -> &libc::itimerspec {
- &self.0
- }
- }
-
- impl From<Expiration> for TimerSpec {
- fn from(expiration: Expiration) -> TimerSpec {
- match expiration {
- Expiration::OneShot(t) => TimerSpec(libc::itimerspec {
- it_interval: zero_init_timespec(),
- it_value: *t.as_ref(),
- }),
- Expiration::IntervalDelayed(start, interval) => {
- TimerSpec(libc::itimerspec {
- it_interval: *interval.as_ref(),
- it_value: *start.as_ref(),
- })
- }
- Expiration::Interval(t) => TimerSpec(libc::itimerspec {
- it_interval: *t.as_ref(),
- it_value: *t.as_ref(),
- }),
- }
- }
- }
-
- /// An enumeration allowing the definition of the expiration time of an alarm,
- /// recurring or not.
- #[derive(Debug, Clone, Copy, Eq, PartialEq)]
- pub enum Expiration {
- /// Alarm will trigger once after the time given in `TimeSpec`
- OneShot(TimeSpec),
- /// Alarm will trigger after a specified delay and then every interval of
- /// time.
- IntervalDelayed(TimeSpec, TimeSpec),
- /// Alarm will trigger every specified interval of time.
- Interval(TimeSpec),
- }
-
- #[cfg(any(target_os = "android", target_os = "linux"))]
- bitflags! {
- /// Flags that are used for arming the timer.
- pub struct TimerSetTimeFlags: libc::c_int {
- const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
- }
- }
- #[cfg(any(
- target_os = "freebsd",
- target_os = "netbsd",
- target_os = "dragonfly",
- target_os = "illumos"
- ))]
- bitflags! {
- /// Flags that are used for arming the timer.
- pub struct TimerSetTimeFlags: libc::c_int {
- const TFD_TIMER_ABSTIME = libc::TIMER_ABSTIME;
- }
- }
-
- impl From<TimerSpec> for Expiration {
- fn from(timerspec: TimerSpec) -> Expiration {
- match timerspec {
- TimerSpec(libc::itimerspec {
- it_interval:
- libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- ..
- },
- it_value: ts,
- }) => Expiration::OneShot(ts.into()),
- TimerSpec(libc::itimerspec {
- it_interval: int_ts,
- it_value: val_ts,
- }) => {
- if (int_ts.tv_sec == val_ts.tv_sec)
- && (int_ts.tv_nsec == val_ts.tv_nsec)
- {
- Expiration::Interval(int_ts.into())
- } else {
- Expiration::IntervalDelayed(
- val_ts.into(),
- int_ts.into(),
- )
- }
- }
- }
- }
- }
-}
-
-pub trait TimeValLike: Sized {
- #[inline]
- fn zero() -> Self {
- Self::seconds(0)
- }
-
- #[inline]
- fn hours(hours: i64) -> Self {
- let secs = hours
- .checked_mul(SECS_PER_HOUR)
- .expect("TimeValLike::hours ouf of bounds");
- Self::seconds(secs)
- }
-
- #[inline]
- fn minutes(minutes: i64) -> Self {
- let secs = minutes
- .checked_mul(SECS_PER_MINUTE)
- .expect("TimeValLike::minutes out of bounds");
- Self::seconds(secs)
- }
-
- fn seconds(seconds: i64) -> Self;
- fn milliseconds(milliseconds: i64) -> Self;
- fn microseconds(microseconds: i64) -> Self;
- fn nanoseconds(nanoseconds: i64) -> Self;
-
- #[inline]
- fn num_hours(&self) -> i64 {
- self.num_seconds() / 3600
- }
-
- #[inline]
- fn num_minutes(&self) -> i64 {
- self.num_seconds() / 60
- }
-
- fn num_seconds(&self) -> i64;
- fn num_milliseconds(&self) -> i64;
- fn num_microseconds(&self) -> i64;
- fn num_nanoseconds(&self) -> i64;
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct TimeSpec(timespec);
-
-const NANOS_PER_SEC: i64 = 1_000_000_000;
-const SECS_PER_MINUTE: i64 = 60;
-const SECS_PER_HOUR: i64 = 3600;
-
-#[cfg(target_pointer_width = "64")]
-const TS_MAX_SECONDS: i64 = (i64::MAX / NANOS_PER_SEC) - 1;
-
-#[cfg(target_pointer_width = "32")]
-const TS_MAX_SECONDS: i64 = isize::MAX as i64;
-
-const TS_MIN_SECONDS: i64 = -TS_MAX_SECONDS;
-
-// x32 compatibility
-// See https://sourceware.org/bugzilla/show_bug.cgi?id=16437
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
-type timespec_tv_nsec_t = i64;
-#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
-type timespec_tv_nsec_t = libc::c_long;
-
-impl From<timespec> for TimeSpec {
- fn from(ts: timespec) -> Self {
- Self(ts)
- }
-}
-
-impl From<Duration> for TimeSpec {
- fn from(duration: Duration) -> Self {
- Self::from_duration(duration)
- }
-}
-
-impl From<TimeSpec> for Duration {
- fn from(timespec: TimeSpec) -> Self {
- Duration::new(timespec.0.tv_sec as u64, timespec.0.tv_nsec as u32)
- }
-}
-
-impl AsRef<timespec> for TimeSpec {
- fn as_ref(&self) -> &timespec {
- &self.0
- }
-}
-
-impl AsMut<timespec> for TimeSpec {
- fn as_mut(&mut self) -> &mut timespec {
- &mut self.0
- }
-}
-
-impl Ord for TimeSpec {
- // The implementation of cmp is simplified by assuming that the struct is
- // normalized. That is, tv_nsec must always be within [0, 1_000_000_000)
- fn cmp(&self, other: &TimeSpec) -> cmp::Ordering {
- if self.tv_sec() == other.tv_sec() {
- self.tv_nsec().cmp(&other.tv_nsec())
- } else {
- self.tv_sec().cmp(&other.tv_sec())
- }
- }
-}
-
-impl PartialOrd for TimeSpec {
- fn partial_cmp(&self, other: &TimeSpec) -> Option<cmp::Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl TimeValLike for TimeSpec {
- #[inline]
- #[cfg_attr(target_env = "musl", allow(deprecated))]
- // https://github.com/rust-lang/libc/issues/1848
- fn seconds(seconds: i64) -> TimeSpec {
- assert!(
- (TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&seconds),
- "TimeSpec out of bounds; seconds={}",
- seconds
- );
- let mut ts = zero_init_timespec();
- ts.tv_sec = seconds as time_t;
- TimeSpec(ts)
- }
-
- #[inline]
- fn milliseconds(milliseconds: i64) -> TimeSpec {
- let nanoseconds = milliseconds
- .checked_mul(1_000_000)
- .expect("TimeSpec::milliseconds out of bounds");
-
- TimeSpec::nanoseconds(nanoseconds)
- }
-
- /// Makes a new `TimeSpec` with given number of microseconds.
- #[inline]
- fn microseconds(microseconds: i64) -> TimeSpec {
- let nanoseconds = microseconds
- .checked_mul(1_000)
- .expect("TimeSpec::milliseconds out of bounds");
-
- TimeSpec::nanoseconds(nanoseconds)
- }
-
- /// Makes a new `TimeSpec` with given number of nanoseconds.
- #[inline]
- #[cfg_attr(target_env = "musl", allow(deprecated))]
- // https://github.com/rust-lang/libc/issues/1848
- fn nanoseconds(nanoseconds: i64) -> TimeSpec {
- let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC);
- assert!(
- (TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&secs),
- "TimeSpec out of bounds"
- );
- let mut ts = zero_init_timespec();
- ts.tv_sec = secs as time_t;
- ts.tv_nsec = nanos as timespec_tv_nsec_t;
- TimeSpec(ts)
- }
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn num_seconds(&self) -> i64 {
- if self.tv_sec() < 0 && self.tv_nsec() > 0 {
- (self.tv_sec() + 1) as i64
- } else {
- self.tv_sec() as i64
- }
- }
-
- fn num_milliseconds(&self) -> i64 {
- self.num_nanoseconds() / 1_000_000
- }
-
- fn num_microseconds(&self) -> i64 {
- self.num_nanoseconds() / 1_000
- }
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn num_nanoseconds(&self) -> i64 {
- let secs = self.num_seconds() * 1_000_000_000;
- let nsec = self.nanos_mod_sec();
- secs + nsec as i64
- }
-}
-
-impl TimeSpec {
- /// Construct a new `TimeSpec` from its components
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- pub const fn new(seconds: time_t, nanoseconds: timespec_tv_nsec_t) -> Self {
- let mut ts = zero_init_timespec();
- ts.tv_sec = seconds;
- ts.tv_nsec = nanoseconds;
- Self(ts)
- }
-
- fn nanos_mod_sec(&self) -> timespec_tv_nsec_t {
- if self.tv_sec() < 0 && self.tv_nsec() > 0 {
- self.tv_nsec() - NANOS_PER_SEC as timespec_tv_nsec_t
- } else {
- self.tv_nsec()
- }
- }
-
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- pub const fn tv_sec(&self) -> time_t {
- self.0.tv_sec
- }
-
- pub const fn tv_nsec(&self) -> timespec_tv_nsec_t {
- self.0.tv_nsec
- }
-
- #[cfg_attr(target_env = "musl", allow(deprecated))]
- // https://github.com/rust-lang/libc/issues/1848
- pub const fn from_duration(duration: Duration) -> Self {
- let mut ts = zero_init_timespec();
- ts.tv_sec = duration.as_secs() as time_t;
- ts.tv_nsec = duration.subsec_nanos() as timespec_tv_nsec_t;
- TimeSpec(ts)
- }
-
- pub const fn from_timespec(timespec: timespec) -> Self {
- Self(timespec)
- }
-}
-
-impl ops::Neg for TimeSpec {
- type Output = TimeSpec;
-
- fn neg(self) -> TimeSpec {
- TimeSpec::nanoseconds(-self.num_nanoseconds())
- }
-}
-
-impl ops::Add for TimeSpec {
- type Output = TimeSpec;
-
- fn add(self, rhs: TimeSpec) -> TimeSpec {
- TimeSpec::nanoseconds(self.num_nanoseconds() + rhs.num_nanoseconds())
- }
-}
-
-impl ops::Sub for TimeSpec {
- type Output = TimeSpec;
-
- fn sub(self, rhs: TimeSpec) -> TimeSpec {
- TimeSpec::nanoseconds(self.num_nanoseconds() - rhs.num_nanoseconds())
- }
-}
-
-impl ops::Mul<i32> for TimeSpec {
- type Output = TimeSpec;
-
- fn mul(self, rhs: i32) -> TimeSpec {
- let usec = self
- .num_nanoseconds()
- .checked_mul(i64::from(rhs))
- .expect("TimeSpec multiply out of bounds");
-
- TimeSpec::nanoseconds(usec)
- }
-}
-
-impl ops::Div<i32> for TimeSpec {
- type Output = TimeSpec;
-
- fn div(self, rhs: i32) -> TimeSpec {
- let usec = self.num_nanoseconds() / i64::from(rhs);
- TimeSpec::nanoseconds(usec)
- }
-}
-
-impl fmt::Display for TimeSpec {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let (abs, sign) = if self.tv_sec() < 0 {
- (-*self, "-")
- } else {
- (*self, "")
- };
-
- let sec = abs.tv_sec();
-
- write!(f, "{}", sign)?;
-
- if abs.tv_nsec() == 0 {
- if abs.tv_sec() == 1 {
- write!(f, "{} second", sec)?;
- } else {
- write!(f, "{} seconds", sec)?;
- }
- } else if abs.tv_nsec() % 1_000_000 == 0 {
- write!(f, "{}.{:03} seconds", sec, abs.tv_nsec() / 1_000_000)?;
- } else if abs.tv_nsec() % 1_000 == 0 {
- write!(f, "{}.{:06} seconds", sec, abs.tv_nsec() / 1_000)?;
- } else {
- write!(f, "{}.{:09} seconds", sec, abs.tv_nsec())?;
- }
-
- Ok(())
- }
-}
-
-#[repr(transparent)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct TimeVal(timeval);
-
-const MICROS_PER_SEC: i64 = 1_000_000;
-
-#[cfg(target_pointer_width = "64")]
-const TV_MAX_SECONDS: i64 = (i64::MAX / MICROS_PER_SEC) - 1;
-
-#[cfg(target_pointer_width = "32")]
-const TV_MAX_SECONDS: i64 = isize::MAX as i64;
-
-const TV_MIN_SECONDS: i64 = -TV_MAX_SECONDS;
-
-impl AsRef<timeval> for TimeVal {
- fn as_ref(&self) -> &timeval {
- &self.0
- }
-}
-
-impl AsMut<timeval> for TimeVal {
- fn as_mut(&mut self) -> &mut timeval {
- &mut self.0
- }
-}
-
-impl Ord for TimeVal {
- // The implementation of cmp is simplified by assuming that the struct is
- // normalized. That is, tv_usec must always be within [0, 1_000_000)
- fn cmp(&self, other: &TimeVal) -> cmp::Ordering {
- if self.tv_sec() == other.tv_sec() {
- self.tv_usec().cmp(&other.tv_usec())
- } else {
- self.tv_sec().cmp(&other.tv_sec())
- }
- }
-}
-
-impl PartialOrd for TimeVal {
- fn partial_cmp(&self, other: &TimeVal) -> Option<cmp::Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl TimeValLike for TimeVal {
- #[inline]
- fn seconds(seconds: i64) -> TimeVal {
- assert!(
- (TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&seconds),
- "TimeVal out of bounds; seconds={}",
- seconds
- );
- #[cfg_attr(target_env = "musl", allow(deprecated))]
- // https://github.com/rust-lang/libc/issues/1848
- TimeVal(timeval {
- tv_sec: seconds as time_t,
- tv_usec: 0,
- })
- }
-
- #[inline]
- fn milliseconds(milliseconds: i64) -> TimeVal {
- let microseconds = milliseconds
- .checked_mul(1_000)
- .expect("TimeVal::milliseconds out of bounds");
-
- TimeVal::microseconds(microseconds)
- }
-
- /// Makes a new `TimeVal` with given number of microseconds.
- #[inline]
- fn microseconds(microseconds: i64) -> TimeVal {
- let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
- assert!(
- (TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&secs),
- "TimeVal out of bounds"
- );
- #[cfg_attr(target_env = "musl", allow(deprecated))]
- // https://github.com/rust-lang/libc/issues/1848
- TimeVal(timeval {
- tv_sec: secs as time_t,
- tv_usec: micros as suseconds_t,
- })
- }
-
- /// Makes a new `TimeVal` with given number of nanoseconds. Some precision
- /// will be lost
- #[inline]
- fn nanoseconds(nanoseconds: i64) -> TimeVal {
- let microseconds = nanoseconds / 1000;
- let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
- assert!(
- (TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&secs),
- "TimeVal out of bounds"
- );
- #[cfg_attr(target_env = "musl", allow(deprecated))]
- // https://github.com/rust-lang/libc/issues/1848
- TimeVal(timeval {
- tv_sec: secs as time_t,
- tv_usec: micros as suseconds_t,
- })
- }
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn num_seconds(&self) -> i64 {
- if self.tv_sec() < 0 && self.tv_usec() > 0 {
- (self.tv_sec() + 1) as i64
- } else {
- self.tv_sec() as i64
- }
- }
-
- fn num_milliseconds(&self) -> i64 {
- self.num_microseconds() / 1_000
- }
-
- // The cast is not unnecessary on all platforms.
- #[allow(clippy::unnecessary_cast)]
- fn num_microseconds(&self) -> i64 {
- let secs = self.num_seconds() * 1_000_000;
- let usec = self.micros_mod_sec();
- secs + usec as i64
- }
-
- fn num_nanoseconds(&self) -> i64 {
- self.num_microseconds() * 1_000
- }
-}
-
-impl TimeVal {
- /// Construct a new `TimeVal` from its components
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- pub const fn new(seconds: time_t, microseconds: suseconds_t) -> Self {
- Self(timeval {
- tv_sec: seconds,
- tv_usec: microseconds,
- })
- }
-
- fn micros_mod_sec(&self) -> suseconds_t {
- if self.tv_sec() < 0 && self.tv_usec() > 0 {
- self.tv_usec() - MICROS_PER_SEC as suseconds_t
- } else {
- self.tv_usec()
- }
- }
-
- #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- pub const fn tv_sec(&self) -> time_t {
- self.0.tv_sec
- }
-
- pub const fn tv_usec(&self) -> suseconds_t {
- self.0.tv_usec
- }
-}
-
-impl ops::Neg for TimeVal {
- type Output = TimeVal;
-
- fn neg(self) -> TimeVal {
- TimeVal::microseconds(-self.num_microseconds())
- }
-}
-
-impl ops::Add for TimeVal {
- type Output = TimeVal;
-
- fn add(self, rhs: TimeVal) -> TimeVal {
- TimeVal::microseconds(self.num_microseconds() + rhs.num_microseconds())
- }
-}
-
-impl ops::Sub for TimeVal {
- type Output = TimeVal;
-
- fn sub(self, rhs: TimeVal) -> TimeVal {
- TimeVal::microseconds(self.num_microseconds() - rhs.num_microseconds())
- }
-}
-
-impl ops::Mul<i32> for TimeVal {
- type Output = TimeVal;
-
- fn mul(self, rhs: i32) -> TimeVal {
- let usec = self
- .num_microseconds()
- .checked_mul(i64::from(rhs))
- .expect("TimeVal multiply out of bounds");
-
- TimeVal::microseconds(usec)
- }
-}
-
-impl ops::Div<i32> for TimeVal {
- type Output = TimeVal;
-
- fn div(self, rhs: i32) -> TimeVal {
- let usec = self.num_microseconds() / i64::from(rhs);
- TimeVal::microseconds(usec)
- }
-}
-
-impl fmt::Display for TimeVal {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let (abs, sign) = if self.tv_sec() < 0 {
- (-*self, "-")
- } else {
- (*self, "")
- };
-
- let sec = abs.tv_sec();
-
- write!(f, "{}", sign)?;
-
- if abs.tv_usec() == 0 {
- if abs.tv_sec() == 1 {
- write!(f, "{} second", sec)?;
- } else {
- write!(f, "{} seconds", sec)?;
- }
- } else if abs.tv_usec() % 1000 == 0 {
- write!(f, "{}.{:03} seconds", sec, abs.tv_usec() / 1000)?;
- } else {
- write!(f, "{}.{:06} seconds", sec, abs.tv_usec())?;
- }
-
- Ok(())
- }
-}
-
-impl From<timeval> for TimeVal {
- fn from(tv: timeval) -> Self {
- TimeVal(tv)
- }
-}
-
-#[inline]
-fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
- (div_floor_64(this, other), mod_floor_64(this, other))
-}
-
-#[inline]
-fn div_floor_64(this: i64, other: i64) -> i64 {
- match div_rem_64(this, other) {
- (d, r) if (r > 0 && other < 0) || (r < 0 && other > 0) => d - 1,
- (d, _) => d,
- }
-}
-
-#[inline]
-fn mod_floor_64(this: i64, other: i64) -> i64 {
- match this % other {
- r if (r > 0 && other < 0) || (r < 0 && other > 0) => r + other,
- r => r,
- }
-}
-
-#[inline]
-fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
- (this / other, this % other)
-}
-
-#[cfg(test)]
-mod test {
- use super::{TimeSpec, TimeVal, TimeValLike};
- use std::time::Duration;
-
- #[test]
- pub fn test_timespec() {
- assert_ne!(TimeSpec::seconds(1), TimeSpec::zero());
- assert_eq!(
- TimeSpec::seconds(1) + TimeSpec::seconds(2),
- TimeSpec::seconds(3)
- );
- assert_eq!(
- TimeSpec::minutes(3) + TimeSpec::seconds(2),
- TimeSpec::seconds(182)
- );
- }
-
- #[test]
- pub fn test_timespec_from() {
- let duration = Duration::new(123, 123_456_789);
- let timespec = TimeSpec::nanoseconds(123_123_456_789);
-
- assert_eq!(TimeSpec::from(duration), timespec);
- assert_eq!(Duration::from(timespec), duration);
- }
-
- #[test]
- pub fn test_timespec_neg() {
- let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123);
- let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123);
-
- assert_eq!(a, -b);
- }
-
- #[test]
- pub fn test_timespec_ord() {
- assert_eq!(TimeSpec::seconds(1), TimeSpec::nanoseconds(1_000_000_000));
- assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001));
- assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999));
- assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999));
- assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001));
- }
-
- #[test]
- pub fn test_timespec_fmt() {
- assert_eq!(TimeSpec::zero().to_string(), "0 seconds");
- assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds");
- assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds");
- assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds");
- assert_eq!(
- TimeSpec::nanoseconds(42).to_string(),
- "0.000000042 seconds"
- );
- assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds");
- }
-
- #[test]
- pub fn test_timeval() {
- assert_ne!(TimeVal::seconds(1), TimeVal::zero());
- assert_eq!(
- TimeVal::seconds(1) + TimeVal::seconds(2),
- TimeVal::seconds(3)
- );
- assert_eq!(
- TimeVal::minutes(3) + TimeVal::seconds(2),
- TimeVal::seconds(182)
- );
- }
-
- #[test]
- pub fn test_timeval_ord() {
- assert_eq!(TimeVal::seconds(1), TimeVal::microseconds(1_000_000));
- assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001));
- assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999));
- assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999));
- assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001));
- }
-
- #[test]
- pub fn test_timeval_neg() {
- let a = TimeVal::seconds(1) + TimeVal::microseconds(123);
- let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123);
-
- assert_eq!(a, -b);
- }
-
- #[test]
- pub fn test_timeval_fmt() {
- assert_eq!(TimeVal::zero().to_string(), "0 seconds");
- assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds");
- assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds");
- assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds");
- assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds");
- assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds");
- }
-}
diff --git a/vendor/nix/src/sys/timer.rs b/vendor/nix/src/sys/timer.rs
deleted file mode 100644
index e1a34051e..000000000
--- a/vendor/nix/src/sys/timer.rs
+++ /dev/null
@@ -1,187 +0,0 @@
-//! Timer API via signals.
-//!
-//! Timer is a POSIX API to create timers and get expiration notifications
-//! through queued Unix signals, for the current process. This is similar to
-//! Linux's timerfd mechanism, except that API is specific to Linux and makes
-//! use of file polling.
-//!
-//! For more documentation, please read [timer_create](https://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_create.html).
-//!
-//! # Examples
-//!
-//! Create an interval timer that signals SIGALARM every 250 milliseconds.
-//!
-//! ```no_run
-//! use nix::sys::signal::{self, SigEvent, SigHandler, SigevNotify, Signal};
-//! use nix::sys::timer::{Expiration, Timer, TimerSetTimeFlags};
-//! use nix::time::ClockId;
-//! use std::convert::TryFrom;
-//! use std::sync::atomic::{AtomicU64, Ordering};
-//! use std::thread::yield_now;
-//! use std::time::Duration;
-//!
-//! const SIG: Signal = Signal::SIGALRM;
-//! static ALARMS: AtomicU64 = AtomicU64::new(0);
-//!
-//! extern "C" fn handle_alarm(signal: libc::c_int) {
-//! let signal = Signal::try_from(signal).unwrap();
-//! if signal == SIG {
-//! ALARMS.fetch_add(1, Ordering::Relaxed);
-//! }
-//! }
-//!
-//! fn main() {
-//! let clockid = ClockId::CLOCK_MONOTONIC;
-//! let sigevent = SigEvent::new(SigevNotify::SigevSignal {
-//! signal: SIG,
-//! si_value: 0,
-//! });
-//!
-//! let mut timer = Timer::new(clockid, sigevent).unwrap();
-//! let expiration = Expiration::Interval(Duration::from_millis(250).into());
-//! let flags = TimerSetTimeFlags::empty();
-//! timer.set(expiration, flags).expect("could not set timer");
-//!
-//! let handler = SigHandler::Handler(handle_alarm);
-//! unsafe { signal::signal(SIG, handler) }.unwrap();
-//!
-//! loop {
-//! let alarms = ALARMS.load(Ordering::Relaxed);
-//! if alarms >= 10 {
-//! println!("total alarms handled: {}", alarms);
-//! break;
-//! }
-//! yield_now()
-//! }
-//! }
-//! ```
-use crate::sys::signal::SigEvent;
-use crate::sys::time::timer::TimerSpec;
-pub use crate::sys::time::timer::{Expiration, TimerSetTimeFlags};
-use crate::time::ClockId;
-use crate::{errno::Errno, Result};
-use core::mem;
-
-/// A Unix signal per-process timer.
-#[derive(Debug)]
-#[repr(transparent)]
-pub struct Timer(libc::timer_t);
-
-impl Timer {
- /// Creates a new timer based on the clock defined by `clockid`. The details
- /// of the signal and its handler are defined by the passed `sigevent`.
- #[doc(alias("timer_create"))]
- pub fn new(clockid: ClockId, mut sigevent: SigEvent) -> Result<Self> {
- let mut timer_id: mem::MaybeUninit<libc::timer_t> =
- mem::MaybeUninit::uninit();
- Errno::result(unsafe {
- libc::timer_create(
- clockid.as_raw(),
- sigevent.as_mut_ptr(),
- timer_id.as_mut_ptr(),
- )
- })
- .map(|_| {
- // SAFETY: libc::timer_create is responsible for initializing
- // timer_id.
- unsafe { Self(timer_id.assume_init()) }
- })
- }
-
- /// Set a new alarm on the timer.
- ///
- /// # Types of alarm
- ///
- /// There are 3 types of alarms you can set:
- ///
- /// - one shot: the alarm will trigger once after the specified amount of
- /// time.
- /// Example: I want an alarm to go off in 60s and then disable itself.
- ///
- /// - interval: the alarm will trigger every specified interval of time.
- /// Example: I want an alarm to go off every 60s. The alarm will first
- /// go off 60s after I set it and every 60s after that. The alarm will
- /// not disable itself.
- ///
- /// - interval delayed: the alarm will trigger after a certain amount of
- /// time and then trigger at a specified interval.
- /// Example: I want an alarm to go off every 60s but only start in 1h.
- /// The alarm will first trigger 1h after I set it and then every 60s
- /// after that. The alarm will not disable itself.
- ///
- /// # Relative vs absolute alarm
- ///
- /// If you do not set any `TimerSetTimeFlags`, then the `TimeSpec` you pass
- /// to the `Expiration` you want is relative. If however you want an alarm
- /// to go off at a certain point in time, you can set `TFD_TIMER_ABSTIME`.
- /// Then the one shot TimeSpec and the delay TimeSpec of the delayed
- /// interval are going to be interpreted as absolute.
- ///
- /// # Disabling alarms
- ///
- /// Note: Only one alarm can be set for any given timer. Setting a new alarm
- /// actually removes the previous one.
- ///
- /// Note: Setting a one shot alarm with a 0s TimeSpec disable the alarm
- /// altogether.
- #[doc(alias("timer_settime"))]
- pub fn set(
- &mut self,
- expiration: Expiration,
- flags: TimerSetTimeFlags,
- ) -> Result<()> {
- let timerspec: TimerSpec = expiration.into();
- Errno::result(unsafe {
- libc::timer_settime(
- self.0,
- flags.bits(),
- timerspec.as_ref(),
- core::ptr::null_mut(),
- )
- })
- .map(drop)
- }
-
- /// Get the parameters for the alarm currently set, if any.
- #[doc(alias("timer_gettime"))]
- pub fn get(&self) -> Result<Option<Expiration>> {
- let mut timerspec = TimerSpec::none();
- Errno::result(unsafe {
- libc::timer_gettime(self.0, timerspec.as_mut())
- })
- .map(|_| {
- if timerspec.as_ref().it_interval.tv_sec == 0
- && timerspec.as_ref().it_interval.tv_nsec == 0
- && timerspec.as_ref().it_value.tv_sec == 0
- && timerspec.as_ref().it_value.tv_nsec == 0
- {
- None
- } else {
- Some(timerspec.into())
- }
- })
- }
-
- /// Return the number of timers that have overrun
- ///
- /// Each timer is able to queue one signal to the process at a time, meaning
- /// if the signal is not handled before the next expiration the timer has
- /// 'overrun'. This function returns how many times that has happened to
- /// this timer, up to `libc::DELAYTIMER_MAX`. If more than the maximum
- /// number of overruns have happened the return is capped to the maximum.
- #[doc(alias("timer_getoverrun"))]
- pub fn overruns(&self) -> i32 {
- unsafe { libc::timer_getoverrun(self.0) }
- }
-}
-
-impl Drop for Timer {
- fn drop(&mut self) {
- if !std::thread::panicking() {
- let result = Errno::result(unsafe { libc::timer_delete(self.0) });
- if let Err(Errno::EINVAL) = result {
- panic!("close of Timer encountered EINVAL");
- }
- }
- }
-}
diff --git a/vendor/nix/src/sys/timerfd.rs b/vendor/nix/src/sys/timerfd.rs
deleted file mode 100644
index a35fc927f..000000000
--- a/vendor/nix/src/sys/timerfd.rs
+++ /dev/null
@@ -1,214 +0,0 @@
-//! Timer API via file descriptors.
-//!
-//! 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)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html).
-//!
-//! # Examples
-//!
-//! Create a new one-shot timer that expires after 1 second.
-//! ```
-//! # use std::os::unix::io::AsRawFd;
-//! # use nix::sys::timerfd::{TimerFd, ClockId, TimerFlags, TimerSetTimeFlags,
-//! # Expiration};
-//! # use nix::sys::time::{TimeSpec, TimeValLike};
-//! # use nix::unistd::read;
-//! #
-//! // We create a new monotonic timer.
-//! let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())
-//! .unwrap();
-//!
-//! // We set a new one-shot timer in 1 seconds.
-//! timer.set(
-//! Expiration::OneShot(TimeSpec::seconds(1)),
-//! TimerSetTimeFlags::empty()
-//! ).unwrap();
-//!
-//! // We wait for the timer to expire.
-//! timer.wait().unwrap();
-//! ```
-use crate::sys::time::timer::TimerSpec;
-pub use crate::sys::time::timer::{Expiration, TimerSetTimeFlags};
-use crate::unistd::read;
-use crate::{errno::Errno, Result};
-use libc::c_int;
-use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
-
-/// A timerfd instance. This is also a file descriptor, you can feed it to
-/// other interfaces consuming file descriptors, epoll for example.
-#[derive(Debug)]
-pub struct TimerFd {
- fd: RawFd,
-}
-
-impl AsRawFd for TimerFd {
- fn as_raw_fd(&self) -> RawFd {
- self.fd
- }
-}
-
-impl FromRawFd for TimerFd {
- unsafe fn from_raw_fd(fd: RawFd) -> Self {
- TimerFd { fd }
- }
-}
-
-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)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html).
- #[repr(i32)]
- #[non_exhaustive]
- pub enum ClockId {
- /// A settable system-wide real-time clock.
- CLOCK_REALTIME,
- /// A non-settable monotonically increasing clock.
- ///
- /// Does not change after system startup.
- /// Does not measure time while the system is suspended.
- CLOCK_MONOTONIC,
- /// Like `CLOCK_MONOTONIC`, except that `CLOCK_BOOTTIME` includes the time
- /// that the system was suspended.
- CLOCK_BOOTTIME,
- /// Like `CLOCK_REALTIME`, but will wake the system if it is suspended.
- CLOCK_REALTIME_ALARM,
- /// Like `CLOCK_BOOTTIME`, but will wake the system if it is suspended.
- CLOCK_BOOTTIME_ALARM,
- }
-}
-
-libc_bitflags! {
- /// Additional flags to change the behaviour of the file descriptor at the
- /// time of creation.
- pub struct TimerFlags: c_int {
- /// Set the `O_NONBLOCK` flag on the open file description referred to by the new file descriptor.
- TFD_NONBLOCK;
- /// Set the `FD_CLOEXEC` flag on the file descriptor.
- TFD_CLOEXEC;
- }
-}
-
-impl TimerFd {
- /// Creates a new timer based on the clock defined by `clockid`. The
- /// underlying fd can be assigned specific flags with `flags` (CLOEXEC,
- /// NONBLOCK). The underlying fd will be closed on drop.
- #[doc(alias("timerfd_create"))]
- pub fn new(clockid: ClockId, flags: TimerFlags) -> Result<Self> {
- Errno::result(unsafe {
- libc::timerfd_create(clockid as i32, flags.bits())
- })
- .map(|fd| Self { fd })
- }
-
- /// Sets a new alarm on the timer.
- ///
- /// # Types of alarm
- ///
- /// There are 3 types of alarms you can set:
- ///
- /// - one shot: the alarm will trigger once after the specified amount of
- /// time.
- /// Example: I want an alarm to go off in 60s and then disable itself.
- ///
- /// - interval: the alarm will trigger every specified interval of time.
- /// Example: I want an alarm to go off every 60s. The alarm will first
- /// go off 60s after I set it and every 60s after that. The alarm will
- /// not disable itself.
- ///
- /// - interval delayed: the alarm will trigger after a certain amount of
- /// time and then trigger at a specified interval.
- /// Example: I want an alarm to go off every 60s but only start in 1h.
- /// The alarm will first trigger 1h after I set it and then every 60s
- /// after that. The alarm will not disable itself.
- ///
- /// # Relative vs absolute alarm
- ///
- /// If you do not set any `TimerSetTimeFlags`, then the `TimeSpec` you pass
- /// to the `Expiration` you want is relative. If however you want an alarm
- /// to go off at a certain point in time, you can set `TFD_TIMER_ABSTIME`.
- /// Then the one shot TimeSpec and the delay TimeSpec of the delayed
- /// interval are going to be interpreted as absolute.
- ///
- /// # Disabling alarms
- ///
- /// Note: Only one alarm can be set for any given timer. Setting a new alarm
- /// actually removes the previous one.
- ///
- /// Note: Setting a one shot alarm with a 0s TimeSpec disables the alarm
- /// altogether.
- #[doc(alias("timerfd_settime"))]
- pub fn set(
- &self,
- expiration: Expiration,
- flags: TimerSetTimeFlags,
- ) -> Result<()> {
- let timerspec: TimerSpec = expiration.into();
- Errno::result(unsafe {
- libc::timerfd_settime(
- self.fd,
- flags.bits(),
- timerspec.as_ref(),
- std::ptr::null_mut(),
- )
- })
- .map(drop)
- }
-
- /// Get the parameters for the alarm currently set, if any.
- #[doc(alias("timerfd_gettime"))]
- pub fn get(&self) -> Result<Option<Expiration>> {
- let mut timerspec = TimerSpec::none();
- Errno::result(unsafe {
- libc::timerfd_gettime(self.fd, timerspec.as_mut())
- })
- .map(|_| {
- if timerspec.as_ref().it_interval.tv_sec == 0
- && timerspec.as_ref().it_interval.tv_nsec == 0
- && timerspec.as_ref().it_value.tv_sec == 0
- && timerspec.as_ref().it_value.tv_nsec == 0
- {
- None
- } else {
- Some(timerspec.into())
- }
- })
- }
-
- /// Remove the alarm if any is set.
- #[doc(alias("timerfd_settime"))]
- pub fn unset(&self) -> Result<()> {
- Errno::result(unsafe {
- libc::timerfd_settime(
- self.fd,
- TimerSetTimeFlags::empty().bits(),
- TimerSpec::none().as_ref(),
- std::ptr::null_mut(),
- )
- })
- .map(drop)
- }
-
- /// Wait for the configured alarm to expire.
- ///
- /// Note: If the alarm is unset, then you will wait forever.
- pub fn wait(&self) -> Result<()> {
- while let Err(e) = read(self.fd, &mut [0u8; 8]) {
- if e != Errno::EINTR {
- return Err(e);
- }
- }
-
- Ok(())
- }
-}
-
-impl Drop for TimerFd {
- fn drop(&mut self) {
- if !std::thread::panicking() {
- let result = Errno::result(unsafe { libc::close(self.fd) });
- if let Err(Errno::EBADF) = result {
- panic!("close of TimerFd encountered EBADF");
- }
- }
- }
-}
diff --git a/vendor/nix/src/sys/uio.rs b/vendor/nix/src/sys/uio.rs
deleted file mode 100644
index b31c3068a..000000000
--- a/vendor/nix/src/sys/uio.rs
+++ /dev/null
@@ -1,291 +0,0 @@
-//! Vectored I/O
-
-use crate::errno::Errno;
-use crate::Result;
-use libc::{self, c_int, c_void, off_t, size_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: &[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)
-}
-
-/// 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 [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)
-}
-
-/// Write to `fd` at `offset` from buffers in `iov`.
-///
-/// Buffers in `iov` will be written in order until all buffers have been written
-/// or an error occurs. The file offset is not changed.
-///
-/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
-#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-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,
- )
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Read from `fd` at `offset` filling buffers in `iov`.
-///
-/// Buffers in `iov` will be filled in order until all buffers have been filled,
-/// no more bytes are available, or an error occurs. The file offset is not
-/// changed.
-///
-/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
-#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-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,
- )
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Low-level write to a file, with specified offset.
-///
-/// See also [pwrite(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html)
-// TODO: move to unistd
-pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
- let res = unsafe {
- libc::pwrite(
- fd,
- buf.as_ptr() as *const c_void,
- buf.len() as size_t,
- offset,
- )
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Low-level read from a file, with specified offset.
-///
-/// See also [pread(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html)
-// TODO: move to unistd
-pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize> {
- let res = unsafe {
- libc::pread(
- fd,
- buf.as_mut_ptr() as *mut c_void,
- buf.len() as size_t,
- offset,
- )
- };
-
- Errno::result(res).map(|r| r as 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 `IoSlice`,
-/// except that it refers to memory in some other process, and is
-/// 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"))]
-#[cfg_attr(docsrs, doc(cfg(all())))]
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct RemoteIoVec {
- /// The starting address of this slice (`iov_base`).
- pub base: usize,
- /// The number of bytes in this slice (`iov_len`).
- 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)]
-#[allow(renamed_and_removed_lints)]
-#[allow(clippy::unknown_clippy_lints)]
-// Clippy false positive: https://github.com/rust-lang/rust-clippy/issues/8867
-#[allow(clippy::derive_partial_eq_without_eq)]
-#[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)
- }
- }
-}
-
-#[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 [`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
-/// number of `remote_iov` chunks.
-///
-/// This requires the same permissions as debugging the process using
-/// [ptrace]: you must either be a privileged process (with
-/// `CAP_SYS_PTRACE`), or you must be running as the same user as the
-/// target process and the OS must have unprivileged debugging enabled.
-///
-/// This function is only available on Linux and Android(SDK23+).
-///
-/// [`process_vm_writev`(2)]: https://man7.org/linux/man-pages/man2/process_vm_writev.2.html
-/// [ptrace]: ../ptrace/index.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: &[IoSlice<'_>],
- remote_iov: &[RemoteIoVec]) -> Result<usize>
-{
- let res = unsafe {
- libc::process_vm_writev(pid.into(),
- local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
- remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-
-/// Read data directly from another process's virtual memory
-/// (see [`process_vm_readv`(2)]).
-///
-/// `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
-/// number of `remote_iov` chunks.
-///
-/// This requires the same permissions as debugging the process using
-/// [`ptrace`]: you must either be a privileged process (with
-/// `CAP_SYS_PTRACE`), or you must be running as the same user as the
-/// target process and the OS must have unprivileged debugging enabled.
-///
-/// This function is only available on Linux and Android(SDK23+).
-///
-/// [`process_vm_readv`(2)]: https://man7.org/linux/man-pages/man2/process_vm_readv.2.html
-/// [`ptrace`]: ../ptrace/index.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: &mut [IoSliceMut<'_>],
- remote_iov: &[RemoteIoVec]) -> Result<usize>
-{
- let res = unsafe {
- libc::process_vm_readv(pid.into(),
- local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
- remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
- };
-
- Errno::result(res).map(|r| r as usize)
-}
-}
diff --git a/vendor/nix/src/sys/utsname.rs b/vendor/nix/src/sys/utsname.rs
deleted file mode 100644
index b48ed9f45..000000000
--- a/vendor/nix/src/sys/utsname.rs
+++ /dev/null
@@ -1,85 +0,0 @@
-//! Get system identification
-use crate::{Errno, Result};
-use libc::c_char;
-use std::ffi::OsStr;
-use std::mem;
-use std::os::unix::ffi::OsStrExt;
-
-/// Describes the running system. Return type of [`uname`].
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[repr(transparent)]
-pub struct UtsName(libc::utsname);
-
-impl UtsName {
- /// Name of the operating system implementation.
- pub fn sysname(&self) -> &OsStr {
- cast_and_trim(&self.0.sysname)
- }
-
- /// Network name of this machine.
- pub fn nodename(&self) -> &OsStr {
- cast_and_trim(&self.0.nodename)
- }
-
- /// Release level of the operating system.
- pub fn release(&self) -> &OsStr {
- cast_and_trim(&self.0.release)
- }
-
- /// Version level of the operating system.
- pub fn version(&self) -> &OsStr {
- cast_and_trim(&self.0.version)
- }
-
- /// Machine hardware platform.
- pub fn machine(&self) -> &OsStr {
- cast_and_trim(&self.0.machine)
- }
-
- /// NIS or YP domain name of this machine.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub fn domainname(&self) -> &OsStr {
- cast_and_trim(&self.0.domainname)
- }
-}
-
-/// Get system identification
-pub fn uname() -> Result<UtsName> {
- unsafe {
- let mut ret = mem::MaybeUninit::zeroed();
- Errno::result(libc::uname(ret.as_mut_ptr()))?;
- Ok(UtsName(ret.assume_init()))
- }
-}
-
-fn cast_and_trim(slice: &[c_char]) -> &OsStr {
- let length = slice
- .iter()
- .position(|&byte| byte == 0)
- .unwrap_or(slice.len());
- let bytes =
- unsafe { std::slice::from_raw_parts(slice.as_ptr().cast(), length) };
-
- OsStr::from_bytes(bytes)
-}
-
-#[cfg(test)]
-mod test {
- #[cfg(target_os = "linux")]
- #[test]
- pub fn test_uname_linux() {
- assert_eq!(super::uname().unwrap().sysname(), "Linux");
- }
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- #[test]
- pub fn test_uname_darwin() {
- assert_eq!(super::uname().unwrap().sysname(), "Darwin");
- }
-
- #[cfg(target_os = "freebsd")]
- #[test]
- pub fn test_uname_freebsd() {
- assert_eq!(super::uname().unwrap().sysname(), "FreeBSD");
- }
-}
diff --git a/vendor/nix/src/sys/wait.rs b/vendor/nix/src/sys/wait.rs
deleted file mode 100644
index b6524e866..000000000
--- a/vendor/nix/src/sys/wait.rs
+++ /dev/null
@@ -1,388 +0,0 @@
-//! Wait for a process to change status
-use crate::errno::Errno;
-use crate::sys::signal::Signal;
-use crate::unistd::Pid;
-use crate::Result;
-use cfg_if::cfg_if;
-use libc::{self, c_int};
-use std::convert::TryFrom;
-#[cfg(any(
- target_os = "android",
- all(target_os = "linux", not(target_env = "uclibc")),
-))]
-use std::os::unix::io::RawFd;
-
-libc_bitflags!(
- /// Controls the behavior of [`waitpid`].
- pub struct WaitPidFlag: c_int {
- /// Do not block when there are no processes wishing to report status.
- WNOHANG;
- /// Report the status of selected processes which are stopped due to a
- /// [`SIGTTIN`](crate::sys::signal::Signal::SIGTTIN),
- /// [`SIGTTOU`](crate::sys::signal::Signal::SIGTTOU),
- /// [`SIGTSTP`](crate::sys::signal::Signal::SIGTSTP), or
- /// [`SIGSTOP`](crate::sys::signal::Signal::SIGSTOP) signal.
- WUNTRACED;
- /// Report the status of selected processes which have terminated.
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "redox",
- target_os = "macos",
- target_os = "netbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- WEXITED;
- /// Report the status of selected processes that have continued from a
- /// job control stop by receiving a
- /// [`SIGCONT`](crate::sys::signal::Signal::SIGCONT) signal.
- WCONTINUED;
- /// An alias for WUNTRACED.
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "redox",
- target_os = "macos",
- target_os = "netbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- WSTOPPED;
- /// Don't reap, just poll status.
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- target_os = "ios",
- target_os = "linux",
- target_os = "redox",
- target_os = "macos",
- target_os = "netbsd"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- WNOWAIT;
- /// Don't wait on children of other threads in this group
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- __WNOTHREAD;
- /// Wait on all children, regardless of type
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- __WALL;
- /// Wait for "clone" children only.
- #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- __WCLONE;
- }
-);
-
-/// Possible return values from `wait()` or `waitpid()`.
-///
-/// Each status (other than `StillAlive`) describes a state transition
-/// in a child process `Pid`, such as the process exiting or stopping,
-/// plus additional data about the transition if any.
-///
-/// Note that there are two Linux-specific enum variants, `PtraceEvent`
-/// and `PtraceSyscall`. Portable code should avoid exhaustively
-/// matching on `WaitStatus`.
-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub enum WaitStatus {
- /// The process exited normally (as with `exit()` or returning from
- /// `main`) with the given exit code. This case matches the C macro
- /// `WIFEXITED(status)`; the second field is `WEXITSTATUS(status)`.
- Exited(Pid, i32),
- /// The process was killed by the given signal. The third field
- /// indicates whether the signal generated a core dump. This case
- /// matches the C macro `WIFSIGNALED(status)`; the last two fields
- /// correspond to `WTERMSIG(status)` and `WCOREDUMP(status)`.
- Signaled(Pid, Signal, bool),
- /// The process is alive, but was stopped by the given signal. This
- /// is only reported if `WaitPidFlag::WUNTRACED` was passed. This
- /// case matches the C macro `WIFSTOPPED(status)`; the second field
- /// is `WSTOPSIG(status)`.
- Stopped(Pid, Signal),
- /// The traced process was stopped by a `PTRACE_EVENT_*` event. See
- /// [`nix::sys::ptrace`] and [`ptrace`(2)] for more information. All
- /// currently-defined events use `SIGTRAP` as the signal; the third
- /// field is the `PTRACE_EVENT_*` value of the event.
- ///
- /// [`nix::sys::ptrace`]: ../ptrace/index.html
- /// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html
- #[cfg(any(target_os = "linux", target_os = "android"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- 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)]: https://man7.org/linux/man-pages/man2/ptrace.2.html
- #[cfg(any(target_os = "linux", target_os = "android"))]
- #[cfg_attr(docsrs, doc(cfg(all())))]
- PtraceSyscall(Pid),
- /// The process was previously stopped but has resumed execution
- /// after receiving a `SIGCONT` signal. This is only reported if
- /// `WaitPidFlag::WCONTINUED` was passed. This case matches the C
- /// macro `WIFCONTINUED(status)`.
- Continued(Pid),
- /// There are currently no state changes to report in any awaited
- /// child process. This is only returned if `WaitPidFlag::WNOHANG`
- /// was used (otherwise `wait()` or `waitpid()` would block until
- /// there was something to report).
- StillAlive,
-}
-
-impl WaitStatus {
- /// Extracts the PID from the WaitStatus unless it equals StillAlive.
- pub fn pid(&self) -> Option<Pid> {
- use self::WaitStatus::*;
- match *self {
- Exited(p, _) | Signaled(p, _, _) | Stopped(p, _) | Continued(p) => {
- Some(p)
- }
- StillAlive => None,
- #[cfg(any(target_os = "android", target_os = "linux"))]
- PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p),
- }
- }
-}
-
-fn exited(status: i32) -> bool {
- libc::WIFEXITED(status)
-}
-
-fn exit_status(status: i32) -> i32 {
- libc::WEXITSTATUS(status)
-}
-
-fn signaled(status: i32) -> bool {
- libc::WIFSIGNALED(status)
-}
-
-fn term_signal(status: i32) -> Result<Signal> {
- Signal::try_from(libc::WTERMSIG(status))
-}
-
-fn dumped_core(status: i32) -> bool {
- libc::WCOREDUMP(status)
-}
-
-fn stopped(status: i32) -> bool {
- libc::WIFSTOPPED(status)
-}
-
-fn stop_signal(status: i32) -> Result<Signal> {
- Signal::try_from(libc::WSTOPSIG(status))
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn syscall_stop(status: i32) -> bool {
- // From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
- // of delivering SIGTRAP | 0x80 as the signal number for syscall
- // stops. This allows easily distinguishing syscall stops from
- // genuine SIGTRAP signals.
- libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn stop_additional(status: i32) -> c_int {
- (status >> 16) as c_int
-}
-
-fn continued(status: i32) -> bool {
- libc::WIFCONTINUED(status)
-}
-
-impl WaitStatus {
- /// Convert a raw `wstatus` as returned by `waitpid`/`wait` into a `WaitStatus`
- ///
- /// # Errors
- ///
- /// Returns an `Error` corresponding to `EINVAL` for invalid status values.
- ///
- /// # Examples
- ///
- /// Convert a `wstatus` obtained from `libc::waitpid` into a `WaitStatus`:
- ///
- /// ```
- /// use nix::sys::wait::WaitStatus;
- /// use nix::sys::signal::Signal;
- /// let pid = nix::unistd::Pid::from_raw(1);
- /// let status = WaitStatus::from_raw(pid, 0x0002);
- /// assert_eq!(status, Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)));
- /// ```
- pub fn from_raw(pid: Pid, status: i32) -> Result<WaitStatus> {
- Ok(if exited(status) {
- WaitStatus::Exited(pid, exit_status(status))
- } else if signaled(status) {
- WaitStatus::Signaled(pid, term_signal(status)?, dumped_core(status))
- } else if stopped(status) {
- cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
- fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
- let status_additional = stop_additional(status);
- Ok(if syscall_stop(status) {
- WaitStatus::PtraceSyscall(pid)
- } else if status_additional == 0 {
- WaitStatus::Stopped(pid, stop_signal(status)?)
- } else {
- WaitStatus::PtraceEvent(pid, stop_signal(status)?,
- stop_additional(status))
- })
- }
- } else {
- fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
- Ok(WaitStatus::Stopped(pid, stop_signal(status)?))
- }
- }
- }
- return decode_stopped(pid, status);
- } else {
- assert!(continued(status));
- WaitStatus::Continued(pid)
- })
- }
-
- /// Convert a `siginfo_t` as returned by `waitid` to a `WaitStatus`
- ///
- /// # Errors
- ///
- /// Returns an `Error` corresponding to `EINVAL` for invalid values.
- ///
- /// # Safety
- ///
- /// siginfo_t is actually a union, not all fields may be initialized.
- /// The functions si_pid() and si_status() must be valid to call on
- /// the passed siginfo_t.
- #[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- all(target_os = "linux", not(target_env = "uclibc")),
- ))]
- unsafe fn from_siginfo(siginfo: &libc::siginfo_t) -> Result<WaitStatus> {
- let si_pid = siginfo.si_pid();
- if si_pid == 0 {
- return Ok(WaitStatus::StillAlive);
- }
-
- assert_eq!(siginfo.si_signo, libc::SIGCHLD);
-
- let pid = Pid::from_raw(si_pid);
- let si_status = siginfo.si_status();
-
- let status = match siginfo.si_code {
- libc::CLD_EXITED => WaitStatus::Exited(pid, si_status),
- libc::CLD_KILLED | libc::CLD_DUMPED => WaitStatus::Signaled(
- pid,
- Signal::try_from(si_status)?,
- siginfo.si_code == libc::CLD_DUMPED,
- ),
- libc::CLD_STOPPED => {
- WaitStatus::Stopped(pid, Signal::try_from(si_status)?)
- }
- libc::CLD_CONTINUED => WaitStatus::Continued(pid),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- libc::CLD_TRAPPED => {
- if si_status == libc::SIGTRAP | 0x80 {
- WaitStatus::PtraceSyscall(pid)
- } else {
- WaitStatus::PtraceEvent(
- pid,
- Signal::try_from(si_status & 0xff)?,
- (si_status >> 8) as c_int,
- )
- }
- }
- _ => return Err(Errno::EINVAL),
- };
-
- Ok(status)
- }
-}
-
-/// Wait for a process to change status
-///
-/// See also [waitpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html)
-pub fn waitpid<P: Into<Option<Pid>>>(
- pid: P,
- options: Option<WaitPidFlag>,
-) -> Result<WaitStatus> {
- use self::WaitStatus::*;
-
- let mut status: i32 = 0;
-
- let option_bits = match options {
- Some(bits) => bits.bits(),
- None => 0,
- };
-
- let res = unsafe {
- libc::waitpid(
- pid.into().unwrap_or_else(|| Pid::from_raw(-1)).into(),
- &mut status as *mut c_int,
- option_bits,
- )
- };
-
- match Errno::result(res)? {
- 0 => Ok(StillAlive),
- res => WaitStatus::from_raw(Pid::from_raw(res), status),
- }
-}
-
-/// Wait for any child process to change status or a signal is received.
-///
-/// See also [wait(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html)
-pub fn wait() -> Result<WaitStatus> {
- waitpid(None, None)
-}
-
-/// The ID argument for `waitid`
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- all(target_os = "linux", not(target_env = "uclibc")),
-))]
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum Id {
- /// Wait for any child
- All,
- /// Wait for the child whose process ID matches the given PID
- Pid(Pid),
- /// Wait for the child whose process group ID matches the given PID
- ///
- /// If the PID is zero, the caller's process group is used since Linux 5.4.
- PGid(Pid),
- /// Wait for the child referred to by the given PID file descriptor
- #[cfg(any(target_os = "android", target_os = "linux"))]
- PIDFd(RawFd),
-}
-
-/// Wait for a process to change status
-///
-/// See also [waitid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitid.html)
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "haiku",
- all(target_os = "linux", not(target_env = "uclibc")),
-))]
-pub fn waitid(id: Id, flags: WaitPidFlag) -> Result<WaitStatus> {
- let (idtype, idval) = match id {
- Id::All => (libc::P_ALL, 0),
- Id::Pid(pid) => (libc::P_PID, pid.as_raw() as libc::id_t),
- Id::PGid(pid) => (libc::P_PGID, pid.as_raw() as libc::id_t),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- Id::PIDFd(fd) => (libc::P_PIDFD, fd as libc::id_t),
- };
-
- let siginfo = unsafe {
- // Memory is zeroed rather than uninitialized, as not all platforms
- // initialize the memory in the StillAlive case
- let mut siginfo: libc::siginfo_t = std::mem::zeroed();
- Errno::result(libc::waitid(idtype, idval, &mut siginfo, flags.bits()))?;
- siginfo
- };
-
- unsafe { WaitStatus::from_siginfo(&siginfo) }
-}