diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:37 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:37 +0000 |
commit | a90a5cba08fdf6c0ceb95101c275108a152a3aed (patch) | |
tree | 532507288f3defd7f4dcf1af49698bcb76034855 /third_party/rust/nix/src/sys | |
parent | Adding debian version 126.0.1-1. (diff) | |
download | firefox-a90a5cba08fdf6c0ceb95101c275108a152a3aed.tar.xz firefox-a90a5cba08fdf6c0ceb95101c275108a152a3aed.zip |
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/nix/src/sys')
36 files changed, 2685 insertions, 3585 deletions
diff --git a/third_party/rust/nix/src/sys/aio.rs b/third_party/rust/nix/src/sys/aio.rs index 5471177e3e..e9213c6434 100644 --- a/third_party/rust/nix/src/sys/aio.rs +++ b/third_party/rust/nix/src/sys/aio.rs @@ -35,7 +35,7 @@ use std::{ ptr, thread, }; -use libc::{c_void, off_t}; +use libc::off_t; use pin_utils::unsafe_pinned; use crate::{ @@ -53,12 +53,9 @@ libc_enum! { /// do it like `fsync` O_SYNC, /// on supported operating systems only, do it like `fdatasync` - #[cfg(any(target_os = "ios", + #[cfg(any(apple_targets, target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + netbsdlike))] O_DSYNC } impl TryFrom<i32> @@ -161,7 +158,7 @@ impl AioCb { let r = unsafe { libc::aio_error(&self.aiocb().0) }; match r { 0 => Ok(()), - num if num > 0 => Err(Errno::from_i32(num)), + num if num > 0 => Err(Errno::from_raw(num)), -1 => Err(Errno::last()), num => panic!("unknown aio_error return value {num:?}"), } @@ -581,7 +578,7 @@ impl<'a> AioRead<'a> { ) -> 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_buf = buf.as_mut_ptr().cast(); aiocb.aiocb.0.aio_lio_opcode = libc::LIO_READ; aiocb.aiocb.0.aio_offset = offs; AioRead { @@ -702,7 +699,7 @@ impl<'a> AioReadv<'a> { // 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_buf = bufs.as_mut_ptr().cast(); aiocb.aiocb.0.aio_lio_opcode = libc::LIO_READV; aiocb.aiocb.0.aio_offset = offs; AioReadv { @@ -817,7 +814,7 @@ impl<'a> AioWrite<'a> { // 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_buf = buf.as_ptr().cast_mut().cast(); aiocb.aiocb.0.aio_lio_opcode = libc::LIO_WRITE; aiocb.aiocb.0.aio_offset = offs; AioWrite { @@ -935,7 +932,7 @@ impl<'a> AioWritev<'a> { // 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_buf = bufs.as_ptr().cast_mut().cast(); aiocb.aiocb.0.aio_lio_opcode = libc::LIO_WRITEV; aiocb.aiocb.0.aio_offset = offs; AioWritev { @@ -1055,7 +1052,8 @@ pub fn aio_suspend( // generic, and accepting arguments like &[AioWrite]. But that would // prevent using aio_suspend to wait on a heterogeneous list of mixed // operations. - let v = list.iter() + let v = list + .iter() .map(|x| x.as_ref() as *const libc::aiocb) .collect::<Vec<*const libc::aiocb>>(); let p = v.as_ptr(); @@ -1175,7 +1173,10 @@ pub fn aio_suspend( /// // notification, we know that all operations are complete. /// assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len()); /// ``` -#[deprecated(since = "0.27.0", note = "https://github.com/nix-rust/nix/issues/2017")] +#[deprecated( + since = "0.27.0", + note = "https://github.com/nix-rust/nix/issues/2017" +)] pub fn lio_listio( mode: LioMode, list: &mut [Pin<&mut dyn AsMut<libc::aiocb>>], @@ -1190,56 +1191,3 @@ pub fn lio_listio( }) .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/third_party/rust/nix/src/sys/epoll.rs b/third_party/rust/nix/src/sys/epoll.rs index 36f9c17d0e..ec146a8c53 100644 --- a/third_party/rust/nix/src/sys/epoll.rs +++ b/third_party/rust/nix/src/sys/epoll.rs @@ -1,4 +1,5 @@ use crate::errno::Errno; +pub use crate::poll_timeout::PollTimeout as EpollTimeout; use crate::Result; use libc::{self, c_int}; use std::mem; @@ -71,32 +72,32 @@ impl EpollEvent { /// A safe wrapper around [`epoll`](https://man7.org/linux/man-pages/man7/epoll.7.html). /// ``` -/// # use nix::sys::{epoll::{Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{eventfd, EfdFlags}}; +/// # use nix::sys::{epoll::{EpollTimeout, Epoll, EpollEvent, EpollFlags, EpollCreateFlags}, eventfd::{EventFd, EfdFlags}}; /// # use nix::unistd::write; -/// # use std::os::unix::io::{OwnedFd, FromRawFd, AsRawFd, AsFd}; +/// # use std::os::unix::io::{OwnedFd, FromRawFd, AsFd}; /// # use std::time::{Instant, Duration}; /// # fn main() -> nix::Result<()> { /// const DATA: u64 = 17; -/// const MILLIS: u64 = 100; +/// const MILLIS: u8 = 100; /// /// // Create epoll /// let epoll = Epoll::new(EpollCreateFlags::empty())?; /// /// // Create eventfd & Add event -/// let eventfd = eventfd(0, EfdFlags::empty())?; +/// let eventfd = EventFd::new()?; /// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?; /// /// // Arm eventfd & Time wait -/// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?; +/// eventfd.arm()?; /// let now = Instant::now(); /// /// // Wait on event /// let mut events = [EpollEvent::empty()]; -/// epoll.wait(&mut events, MILLIS as isize)?; +/// epoll.wait(&mut events, MILLIS)?; /// /// // Assert data correct & timeout didn't occur /// assert_eq!(events[0].data(), DATA); -/// assert!(now.elapsed() < Duration::from_millis(MILLIS)); +/// assert!(now.elapsed().as_millis() < MILLIS.into()); /// # Ok(()) /// # } /// ``` @@ -140,17 +141,17 @@ impl Epoll { /// (This can be thought of as fetching items from the ready list of the epoll instance.) /// /// [`epoll_wait`](https://man7.org/linux/man-pages/man2/epoll_wait.2.html) - pub fn wait( + pub fn wait<T: Into<EpollTimeout>>( &self, events: &mut [EpollEvent], - timeout: isize, + timeout: T, ) -> Result<usize> { let res = unsafe { libc::epoll_wait( self.0.as_raw_fd(), - events.as_mut_ptr() as *mut libc::epoll_event, + events.as_mut_ptr().cast(), events.len() as c_int, - timeout as c_int, + timeout.into().into(), ) }; @@ -240,7 +241,7 @@ pub fn epoll_wait( let res = unsafe { libc::epoll_wait( epfd, - events.as_mut_ptr() as *mut libc::epoll_event, + events.as_mut_ptr().cast(), events.len() as c_int, timeout_ms as c_int, ) diff --git a/third_party/rust/nix/src/sys/event.rs b/third_party/rust/nix/src/sys/event.rs index ec7f7e277a..b294d27c70 100644 --- a/third_party/rust/nix/src/sys/event.rs +++ b/third_party/rust/nix/src/sys/event.rs @@ -10,6 +10,7 @@ use libc::{c_int, c_long, intptr_t, time_t, timespec, uintptr_t}; use libc::{c_long, intptr_t, size_t, time_t, timespec, uintptr_t}; use std::convert::TryInto; use std::mem; +use std::os::fd::{AsFd, BorrowedFd}; use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd}; use std::ptr; @@ -29,6 +30,18 @@ pub struct KEvent { #[derive(Debug)] pub struct Kqueue(OwnedFd); +impl AsFd for Kqueue { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +impl From<Kqueue> for OwnedFd { + fn from(value: Kqueue) -> Self { + value.0 + } +} + impl Kqueue { /// Create a new kernel event queue. pub fn new() -> Result<Self> { @@ -63,9 +76,9 @@ impl Kqueue { let res = unsafe { libc::kevent( self.0.as_raw_fd(), - changelist.as_ptr() as *const libc::kevent, + changelist.as_ptr().cast(), changelist.len() as type_of_nchanges, - eventlist.as_mut_ptr() as *mut libc::kevent, + eventlist.as_mut_ptr().cast(), eventlist.len() as type_of_nchanges, if let Some(ref timeout) = timeout_opt { timeout as *const timespec @@ -78,13 +91,7 @@ impl Kqueue { } } -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "openbsd" -))] +#[cfg(any(freebsdlike, apple_targets, target_os = "openbsd"))] type type_of_udata = *mut libc::c_void; #[cfg(target_os = "netbsd")] type type_of_udata = intptr_t; @@ -109,10 +116,7 @@ libc_enum! { /// Takes a descriptor as the identifier, and returns whenever one of /// the specified exceptional conditions has occurred on the descriptor. EVFILT_EXCEPT, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos"))] + #[cfg(any(freebsdlike, apple_targets))] /// Establishes a file system monitor. EVFILT_FS, #[cfg(target_os = "freebsd")] @@ -120,7 +124,7 @@ libc_enum! { /// # See Also /// [lio_listio(2)](https://www.freebsd.org/cgi/man.cgi?query=lio_listio) EVFILT_LIO, - #[cfg(any(target_os = "ios", target_os = "macos"))] + #[cfg(apple_targets)] /// Mach portsets EVFILT_MACHPORT, /// Notifies when a process performs one or more of the requested @@ -144,13 +148,10 @@ libc_enum! { EVFILT_SIGNAL, /// Establishes a timer and notifies when the timer expires. EVFILT_TIMER, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos"))] + #[cfg(any(freebsdlike, apple_targets))] /// Notifies only when explicitly requested by the user. EVFILT_USER, - #[cfg(any(target_os = "ios", target_os = "macos"))] + #[cfg(apple_targets)] /// Virtual memory events EVFILT_VM, /// Notifies when a requested event happens on a specified file. @@ -162,13 +163,7 @@ libc_enum! { impl TryFrom<type_of_event_filter> } -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "openbsd" -))] +#[cfg(any(freebsdlike, apple_targets, target_os = "openbsd"))] #[doc(hidden)] pub type type_of_event_flag = u16; #[cfg(target_os = "netbsd")] @@ -187,9 +182,7 @@ libc_bitflags! { EV_DELETE; #[allow(missing_docs)] EV_DISABLE; - #[cfg(any(target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", target_os = "macos", - target_os = "netbsd", target_os = "openbsd"))] + #[cfg(bsd)] #[allow(missing_docs)] EV_DISPATCH; #[cfg(target_os = "freebsd")] @@ -201,7 +194,7 @@ libc_bitflags! { EV_EOF; #[allow(missing_docs)] EV_ERROR; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] EV_FLAG0; #[allow(missing_docs)] @@ -211,15 +204,13 @@ libc_bitflags! { EV_NODATA; #[allow(missing_docs)] EV_ONESHOT; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] EV_OOBAND; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] EV_POLL; - #[cfg(any(target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", target_os = "macos", - target_os = "netbsd", target_os = "openbsd"))] + #[cfg(bsd)] #[allow(missing_docs)] EV_RECEIPT; } @@ -231,7 +222,7 @@ libc_bitflags!( // that wouldn't simply be repeating the man page. #[allow(missing_docs)] pub struct FilterFlag: u32 { - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] NOTE_ABSOLUTE; #[allow(missing_docs)] @@ -247,45 +238,27 @@ libc_bitflags!( NOTE_EXEC; #[allow(missing_docs)] NOTE_EXIT; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] NOTE_EXITSTATUS; #[allow(missing_docs)] NOTE_EXTEND; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] + #[cfg(any(apple_targets, freebsdlike))] #[allow(missing_docs)] NOTE_FFAND; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] + #[cfg(any(apple_targets, freebsdlike))] #[allow(missing_docs)] NOTE_FFCOPY; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] + #[cfg(any(apple_targets, freebsdlike))] #[allow(missing_docs)] NOTE_FFCTRLMASK; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] + #[cfg(any(apple_targets, freebsdlike))] #[allow(missing_docs)] NOTE_FFLAGSMASK; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] + #[cfg(any(apple_targets, freebsdlike))] #[allow(missing_docs)] NOTE_FFNOP; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] + #[cfg(any(apple_targets, freebsdlike))] #[allow(missing_docs)] NOTE_FFOR; #[allow(missing_docs)] @@ -297,10 +270,12 @@ libc_bitflags!( #[cfg(target_os = "freebsd")] #[allow(missing_docs)] NOTE_MSECONDS; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] NOTE_NONE; - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] + #[cfg(any( + apple_targets, + target_os = "freebsd"))] #[allow(missing_docs)] NOTE_NSECONDS; #[cfg(target_os = "dragonfly")] @@ -314,38 +289,39 @@ libc_bitflags!( NOTE_RENAME; #[allow(missing_docs)] NOTE_REVOKE; - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] + #[cfg(any( + apple_targets, + target_os = "freebsd"))] #[allow(missing_docs)] NOTE_SECONDS; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] NOTE_SIGNAL; #[allow(missing_docs)] NOTE_TRACK; #[allow(missing_docs)] NOTE_TRACKERR; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] + #[cfg(any(apple_targets, freebsdlike))] #[allow(missing_docs)] NOTE_TRIGGER; #[cfg(target_os = "openbsd")] #[allow(missing_docs)] NOTE_TRUNCATE; - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] + #[cfg(any( + apple_targets, + target_os = "freebsd"))] #[allow(missing_docs)] NOTE_USECONDS; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] NOTE_VM_ERROR; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] NOTE_VM_PRESSURE; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] NOTE_VM_PRESSURE_SUDDEN_TERMINATE; - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] #[allow(missing_docs)] NOTE_VM_PRESSURE_TERMINATE; #[allow(missing_docs)] @@ -443,13 +419,7 @@ pub fn kevent( kq.kevent(changelist, eventlist, Some(timeout)) } -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd" -))] +#[cfg(any(apple_targets, freebsdlike, target_os = "openbsd"))] type type_of_nchanges = c_int; #[cfg(target_os = "netbsd")] type type_of_nchanges = size_t; @@ -484,42 +454,3 @@ pub fn ev_set( 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/third_party/rust/nix/src/sys/eventfd.rs b/third_party/rust/nix/src/sys/eventfd.rs index f1723519cf..50a4f091bd 100644 --- a/third_party/rust/nix/src/sys/eventfd.rs +++ b/third_party/rust/nix/src/sys/eventfd.rs @@ -1,17 +1,84 @@ use crate::errno::Errno; -use crate::Result; -use std::os::unix::io::{FromRawFd, OwnedFd}; +use crate::{Result,unistd}; +use std::os::unix::io::{FromRawFd, OwnedFd, AsRawFd, AsFd, RawFd, BorrowedFd}; 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 + EFD_CLOEXEC; // Since Linux 2.6.27/FreeBSD 13.0 + EFD_NONBLOCK; // Since Linux 2.6.27/FreeBSD 13.0 + EFD_SEMAPHORE; // Since Linux 2.6.30/FreeBSD 13.0 } } +#[deprecated(since = "0.28.0", note = "Use EventFd::from_value_and_flags() instead")] pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<OwnedFd> { let res = unsafe { libc::eventfd(initval, flags.bits()) }; Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r) }) } + +#[derive(Debug)] +#[repr(transparent)] +pub struct EventFd(OwnedFd); +impl EventFd { + /// [`EventFd::from_value_and_flags`] with `init_val = 0` and `flags = EfdFlags::empty()`. + pub fn new() -> Result<Self> { + Self::from_value_and_flags(0, EfdFlags::empty()) + } + /// Constructs [`EventFd`] with the given `init_val` and `flags`. + /// + /// Wrapper around [`libc::eventfd`]. + pub fn from_value_and_flags(init_val: u32, flags: EfdFlags) -> Result<Self> { + let res = unsafe { libc::eventfd(init_val, flags.bits()) }; + Errno::result(res).map(|r| Self(unsafe { OwnedFd::from_raw_fd(r) })) + } + /// [`EventFd::from_value_and_flags`] with `init_val = 0` and given `flags`. + pub fn from_flags(flags: EfdFlags) -> Result<Self> { + Self::from_value_and_flags(0, flags) + } + /// [`EventFd::from_value_and_flags`] with given `init_val` and `flags = EfdFlags::empty()`. + pub fn from_value(init_val: u32) -> Result<Self> { + Self::from_value_and_flags(init_val, EfdFlags::empty()) + } + /// Arms `self`, a following call to `poll`, `select` or `epoll` will return immediately. + /// + /// [`EventFd::write`] with `1`. + pub fn arm(&self) -> Result<usize> { + self.write(1) + } + /// Defuses `self`, a following call to `poll`, `select` or `epoll` will block. + /// + /// [`EventFd::write`] with `0`. + pub fn defuse(&self) -> Result<usize> { + self.write(0) + } + /// Enqueues `value` triggers. + /// + /// The next `value` calls to `poll`, `select` or `epoll` will return immediately. + /// + /// [`EventFd::write`] with `value`. + pub fn write(&self, value: u64) -> Result<usize> { + unistd::write(&self.0,&value.to_ne_bytes()) + } + // Reads the value from the file descriptor. + pub fn read(&self) -> Result<u64> { + let mut arr = [0; std::mem::size_of::<u64>()]; + unistd::read(self.0.as_raw_fd(),&mut arr)?; + Ok(u64::from_ne_bytes(arr)) + } +} +impl AsFd for EventFd { + fn as_fd(&self) -> BorrowedFd { + self.0.as_fd() + } +} +impl AsRawFd for EventFd { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} +impl From<EventFd> for OwnedFd { + fn from(x: EventFd) -> OwnedFd { + x.0 + } +} diff --git a/third_party/rust/nix/src/sys/fanotify.rs b/third_party/rust/nix/src/sys/fanotify.rs new file mode 100644 index 0000000000..e217406e02 --- /dev/null +++ b/third_party/rust/nix/src/sys/fanotify.rs @@ -0,0 +1,416 @@ +//! Monitoring API for filesystem events. +//! +//! Fanotify is a Linux-only API to monitor filesystems events. +//! +//! Additional capabilities compared to the `inotify` API include the ability to +//! monitor all of the objects in a mounted filesystem, the ability to make +//! access permission decisions, and the possibility to read or modify files +//! before access by other applications. +//! +//! For more documentation, please read +//! [fanotify(7)](https://man7.org/linux/man-pages/man7/fanotify.7.html). + +use crate::errno::Errno; +use crate::fcntl::{at_rawfd, OFlag}; +use crate::unistd::{close, read, write}; +use crate::{NixPath, Result}; +use std::marker::PhantomData; +use std::mem::{size_of, MaybeUninit}; +use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd}; +use std::ptr; + +libc_bitflags! { + /// Mask for defining which events shall be listened with + /// [`fanotify_mark`](fn.fanotify_mark.html) and for querying notifications. + pub struct MaskFlags: u64 { + /// File was accessed. + FAN_ACCESS; + /// File was modified. + FAN_MODIFY; + /// Metadata has changed. Since Linux 5.1. + FAN_ATTRIB; + /// Writtable file was closed. + FAN_CLOSE_WRITE; + /// Unwrittable file was closed. + FAN_CLOSE_NOWRITE; + /// File was opened. + FAN_OPEN; + /// File was moved from X. Since Linux 5.1. + FAN_MOVED_FROM; + /// File was moved to Y. Since Linux 5.1. + FAN_MOVED_TO; + /// Subfile was created. Since Linux 5.1. + FAN_CREATE; + /// Subfile was deleted. Since Linux 5.1. + FAN_DELETE; + /// Self was deleted. Since Linux 5.1. + FAN_DELETE_SELF; + /// Self was moved. Since Linux 5.1. + FAN_MOVE_SELF; + /// File was opened for execution. Since Linux 5.0. + FAN_OPEN_EXEC; + + /// Event queue overflowed. + FAN_Q_OVERFLOW; + /// Filesystem error. Since Linux 5.16. + FAN_FS_ERROR; + + /// Permission to open file was requested. + FAN_OPEN_PERM; + /// Permission to access file was requested. + FAN_ACCESS_PERM; + /// Permission to open file for execution was requested. Since Linux + /// 5.0. + FAN_OPEN_EXEC_PERM; + + /// Interested in child events. + FAN_EVENT_ON_CHILD; + + /// File was renamed. Since Linux 5.17. + FAN_RENAME; + + /// Event occurred against dir. + FAN_ONDIR; + + /// Combination of `FAN_CLOSE_WRITE` and `FAN_CLOSE_NOWRITE`. + FAN_CLOSE; + /// Combination of `FAN_MOVED_FROM` and `FAN_MOVED_TO`. + FAN_MOVE; + } +} + +libc_bitflags! { + /// Configuration options for [`fanotify_init`](fn.fanotify_init.html). + pub struct InitFlags: libc::c_uint { + /// Close-on-exec flag set on the file descriptor. + FAN_CLOEXEC; + /// Nonblocking flag set on the file descriptor. + FAN_NONBLOCK; + + /// Receipt of events notifications. + FAN_CLASS_NOTIF; + /// Receipt of events for permission decisions, after they contain final + /// data. + FAN_CLASS_CONTENT; + /// Receipt of events for permission decisions, before they contain + /// final data. + FAN_CLASS_PRE_CONTENT; + + /// Remove the limit of 16384 events for the event queue. + FAN_UNLIMITED_QUEUE; + /// Remove the limit of 8192 marks. + FAN_UNLIMITED_MARKS; + + /// Make `FanotifyEvent::pid` return pidfd. Since Linux 5.15. + FAN_REPORT_PIDFD; + /// Make `FanotifyEvent::pid` return thread id. Since Linux 4.20. + FAN_REPORT_TID; + } +} + +libc_bitflags! { + /// File status flags for fanotify events file descriptors. + pub struct EventFFlags: libc::c_uint { + /// Read only access. + O_RDONLY as libc::c_uint; + /// Write only access. + O_WRONLY as libc::c_uint; + /// Read and write access. + O_RDWR as libc::c_uint; + /// Support for files exceeded 2 GB. + O_LARGEFILE as libc::c_uint; + /// Close-on-exec flag for the file descriptor. Since Linux 3.18. + O_CLOEXEC as libc::c_uint; + /// Append mode for the file descriptor. + O_APPEND as libc::c_uint; + /// Synchronized I/O data integrity completion. + O_DSYNC as libc::c_uint; + /// No file last access time update. + O_NOATIME as libc::c_uint; + /// Nonblocking mode for the file descriptor. + O_NONBLOCK as libc::c_uint; + /// Synchronized I/O file integrity completion. + O_SYNC as libc::c_uint; + } +} + +impl TryFrom<OFlag> for EventFFlags { + type Error = Errno; + + fn try_from(o_flag: OFlag) -> Result<Self> { + EventFFlags::from_bits(o_flag.bits() as u32).ok_or(Errno::EINVAL) + } +} + +impl From<EventFFlags> for OFlag { + fn from(event_f_flags: EventFFlags) -> Self { + OFlag::from_bits_retain(event_f_flags.bits() as i32) + } +} + +libc_bitflags! { + /// Configuration options for [`fanotify_mark`](fn.fanotify_mark.html). + pub struct MarkFlags: libc::c_uint { + /// Add the events to the marks. + FAN_MARK_ADD; + /// Remove the events to the marks. + FAN_MARK_REMOVE; + /// Don't follow symlinks, mark them. + FAN_MARK_DONT_FOLLOW; + /// Raise an error if filesystem to be marked is not a directory. + FAN_MARK_ONLYDIR; + /// Events added to or removed from the marks. + FAN_MARK_IGNORED_MASK; + /// Ignore mask shall survive modify events. + FAN_MARK_IGNORED_SURV_MODIFY; + /// Remove all marks. + FAN_MARK_FLUSH; + /// Do not pin inode object in the inode cache. Since Linux 5.19. + FAN_MARK_EVICTABLE; + /// Events added to or removed from the marks. Since Linux 6.0. + FAN_MARK_IGNORE; + + /// Default flag. + FAN_MARK_INODE; + /// Mark the mount specified by pathname. + FAN_MARK_MOUNT; + /// Mark the filesystem specified by pathname. Since Linux 4.20. + FAN_MARK_FILESYSTEM; + + /// Combination of `FAN_MARK_IGNORE` and `FAN_MARK_IGNORED_SURV_MODIFY`. + FAN_MARK_IGNORE_SURV; + } +} + +/// Compile version number of fanotify API. +pub const FANOTIFY_METADATA_VERSION: u8 = libc::FANOTIFY_METADATA_VERSION; + +/// Abstract over `libc::fanotify_event_metadata`, which represents an event +/// received via `Fanotify::read_events`. +// Is not Clone due to fd field, to avoid use-after-close scenarios. +#[derive(Debug, Eq, Hash, PartialEq)] +#[repr(transparent)] +#[allow(missing_copy_implementations)] +pub struct FanotifyEvent(libc::fanotify_event_metadata); + +impl FanotifyEvent { + /// Version number for the structure. It must be compared to + /// `FANOTIFY_METADATA_VERSION` to verify compile version and runtime + /// version does match. It can be done with the + /// `FanotifyEvent::check_version` method. + pub fn version(&self) -> u8 { + self.0.vers + } + + /// Checks that compile fanotify API version is equal to the version of the + /// event. + pub fn check_version(&self) -> bool { + self.version() == FANOTIFY_METADATA_VERSION + } + + /// Mask flags of the events. + pub fn mask(&self) -> MaskFlags { + MaskFlags::from_bits_truncate(self.0.mask) + } + + /// The file descriptor of the event. If the value is `None` when reading + /// from the fanotify group, this event is to notify that a group queue + /// overflow occured. + pub fn fd(&self) -> Option<BorrowedFd> { + if self.0.fd == libc::FAN_NOFD { + None + } else { + // SAFETY: self.0.fd will be opened for the lifetime of `Self`, + // which is longer than the lifetime of the returned BorrowedFd, so + // it is safe. + Some(unsafe { BorrowedFd::borrow_raw(self.0.fd) }) + } + } + + /// PID of the process that caused the event. TID in case flag + /// `FAN_REPORT_TID` was set at group initialization. + pub fn pid(&self) -> i32 { + self.0.pid + } +} + +impl Drop for FanotifyEvent { + fn drop(&mut self) { + let e = close(self.0.fd); + if !std::thread::panicking() && e == Err(Errno::EBADF) { + panic!("Closing an invalid file descriptor!"); + }; + } +} + +/// Abstraction over the structure to be sent to allow or deny a given event. +#[derive(Debug)] +#[repr(transparent)] +pub struct FanotifyResponse<'a> { + inner: libc::fanotify_response, + _borrowed_fd: PhantomData<BorrowedFd<'a>>, +} + +impl<'a> FanotifyResponse<'a> { + /// Create a new response. + pub fn new(fd: BorrowedFd<'a>, response: Response) -> Self { + Self { + inner: libc::fanotify_response { + fd: fd.as_raw_fd(), + response: response.bits(), + }, + _borrowed_fd: PhantomData, + } + } +} + +libc_bitflags! { + /// Response to be wrapped in `FanotifyResponse` and sent to the `Fanotify` + /// group to allow or deny an event. + pub struct Response: u32 { + /// Allow the event. + FAN_ALLOW; + /// Deny the event. + FAN_DENY; + } +} + +/// A fanotify group. This is also a file descriptor that can feed to other +/// interfaces consuming file descriptors. +#[derive(Debug)] +pub struct Fanotify { + fd: OwnedFd, +} + +impl Fanotify { + /// Initialize a new fanotify group. + /// + /// Returns a Result containing a Fanotify instance. + /// + /// For more information, see [fanotify_init(2)](https://man7.org/linux/man-pages/man7/fanotify_init.2.html). + pub fn init( + flags: InitFlags, + event_f_flags: EventFFlags, + ) -> Result<Fanotify> { + let res = Errno::result(unsafe { + libc::fanotify_init(flags.bits(), event_f_flags.bits()) + }); + res.map(|fd| Fanotify { + fd: unsafe { OwnedFd::from_raw_fd(fd) }, + }) + } + + /// Add, remove, or modify an fanotify mark on a filesystem object. + /// If `dirfd` is `None`, `AT_FDCWD` is used. + /// + /// Returns a Result containing either `()` on success or errno otherwise. + /// + /// For more information, see [fanotify_mark(2)](https://man7.org/linux/man-pages/man7/fanotify_mark.2.html). + pub fn mark<P: ?Sized + NixPath>( + &self, + flags: MarkFlags, + mask: MaskFlags, + dirfd: Option<RawFd>, + path: Option<&P>, + ) -> Result<()> { + fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T> + where + P: ?Sized + NixPath, + F: FnOnce(*const libc::c_char) -> T, + { + match p { + Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())), + None => Ok(f(std::ptr::null())), + } + } + + let res = with_opt_nix_path(path, |p| unsafe { + libc::fanotify_mark( + self.fd.as_raw_fd(), + flags.bits(), + mask.bits(), + at_rawfd(dirfd), + p, + ) + })?; + + Errno::result(res).map(|_| ()) + } + + /// Read incoming events from the fanotify group. + /// + /// Returns a Result containing either a `Vec` of events on success or errno + /// otherwise. + /// + /// # Errors + /// + /// Possible errors can be those that are explicitly listed in + /// [fanotify(2)](https://man7.org/linux/man-pages/man7/fanotify.2.html) in + /// addition to the possible errors caused by `read` call. + /// In particular, `EAGAIN` is returned when no event is available on a + /// group that has been initialized with the flag `InitFlags::FAN_NONBLOCK`, + /// thus making this method nonblocking. + pub fn read_events(&self) -> Result<Vec<FanotifyEvent>> { + let metadata_size = size_of::<libc::fanotify_event_metadata>(); + const BUFSIZ: usize = 4096; + let mut buffer = [0u8; BUFSIZ]; + let mut events = Vec::new(); + let mut offset = 0; + + let nread = read(self.fd.as_raw_fd(), &mut buffer)?; + + while (nread - offset) >= metadata_size { + let metadata = unsafe { + let mut metadata = + MaybeUninit::<libc::fanotify_event_metadata>::uninit(); + ptr::copy_nonoverlapping( + buffer.as_ptr().add(offset), + metadata.as_mut_ptr().cast(), + (BUFSIZ - offset).min(metadata_size), + ); + metadata.assume_init() + }; + + events.push(FanotifyEvent(metadata)); + offset += metadata.event_len as usize; + } + + Ok(events) + } + + /// Write an event response on the fanotify group. + /// + /// Returns a Result containing either `()` on success or errno otherwise. + /// + /// # Errors + /// + /// Possible errors can be those that are explicitly listed in + /// [fanotify(2)](https://man7.org/linux/man-pages/man7/fanotify.2.html) in + /// addition to the possible errors caused by `write` call. + /// In particular, `EAGAIN` or `EWOULDBLOCK` is returned when no event is + /// available on a group that has been initialized with the flag + /// `InitFlags::FAN_NONBLOCK`, thus making this method nonblocking. + pub fn write_response(&self, response: FanotifyResponse) -> Result<()> { + write(self.fd.as_fd(), unsafe { + std::slice::from_raw_parts( + (&response.inner as *const libc::fanotify_response).cast(), + size_of::<libc::fanotify_response>(), + ) + })?; + Ok(()) + } +} + +impl FromRawFd for Fanotify { + unsafe fn from_raw_fd(fd: RawFd) -> Self { + Fanotify { + fd: unsafe { OwnedFd::from_raw_fd(fd) }, + } + } +} + +impl AsFd for Fanotify { + fn as_fd(&'_ self) -> BorrowedFd<'_> { + self.fd.as_fd() + } +} diff --git a/third_party/rust/nix/src/sys/inotify.rs b/third_party/rust/nix/src/sys/inotify.rs index e5fe930f49..9cbeb53973 100644 --- a/third_party/rust/nix/src/sys/inotify.rs +++ b/third_party/rust/nix/src/sys/inotify.rs @@ -143,7 +143,9 @@ impl Inotify { pub fn init(flags: InitFlags) -> Result<Inotify> { let res = Errno::result(unsafe { libc::inotify_init1(flags.bits()) }); - res.map(|fd| Inotify { fd: unsafe { OwnedFd::from_raw_fd(fd) } }) + res.map(|fd| Inotify { + fd: unsafe { OwnedFd::from_raw_fd(fd) }, + }) } /// Adds a new watch on the target file or directory. @@ -157,7 +159,11 @@ impl Inotify { mask: AddWatchFlags, ) -> Result<WatchDescriptor> { let res = path.with_nix_path(|cstr| unsafe { - libc::inotify_add_watch(self.fd.as_raw_fd(), cstr.as_ptr(), mask.bits()) + libc::inotify_add_watch( + self.fd.as_raw_fd(), + cstr.as_ptr(), + mask.bits(), + ) })?; Errno::result(res).map(|wd| WatchDescriptor { wd }) @@ -202,7 +208,7 @@ impl Inotify { let mut event = MaybeUninit::<libc::inotify_event>::uninit(); ptr::copy_nonoverlapping( buffer.as_ptr().add(offset), - event.as_mut_ptr() as *mut u8, + event.as_mut_ptr().cast(), (BUFSIZ - offset).min(header_size), ); event.assume_init() @@ -237,7 +243,9 @@ impl Inotify { impl FromRawFd for Inotify { unsafe fn from_raw_fd(fd: RawFd) -> Self { - Inotify { fd: OwnedFd::from_raw_fd(fd) } + Inotify { + fd: unsafe { OwnedFd::from_raw_fd(fd) }, + } } } diff --git a/third_party/rust/nix/src/sys/ioctl/bsd.rs b/third_party/rust/nix/src/sys/ioctl/bsd.rs index 307994cb96..cedc8e63fe 100644 --- a/third_party/rust/nix/src/sys/ioctl/bsd.rs +++ b/third_party/rust/nix/src/sys/ioctl/bsd.rs @@ -1,10 +1,10 @@ /// The datatype used for the ioctl number #[doc(hidden)] -#[cfg(not(target_os = "illumos"))] +#[cfg(not(solarish))] pub type ioctl_num_type = ::libc::c_ulong; #[doc(hidden)] -#[cfg(target_os = "illumos")] +#[cfg(solarish)] pub type ioctl_num_type = ::libc::c_int; /// The datatype used for the 3rd argument diff --git a/third_party/rust/nix/src/sys/ioctl/linux.rs b/third_party/rust/nix/src/sys/ioctl/linux.rs index 610b8ddac0..52312f4f04 100644 --- a/third_party/rust/nix/src/sys/ioctl/linux.rs +++ b/third_party/rust/nix/src/sys/ioctl/linux.rs @@ -19,7 +19,9 @@ pub const TYPEBITS: ioctl_num_type = 8; cfg_if! { if #[cfg(any( target_arch = "mips", + target_arch = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "sparc64" diff --git a/third_party/rust/nix/src/sys/ioctl/mod.rs b/third_party/rust/nix/src/sys/ioctl/mod.rs index 0b3fe3e769..e1e808f19e 100644 --- a/third_party/rust/nix/src/sys/ioctl/mod.rs +++ b/third_party/rust/nix/src/sys/ioctl/mod.rs @@ -72,7 +72,7 @@ //! # 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); +//! let res = unsafe { libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data) }; //! Errno::result(res) //! } //! # fn main() {} @@ -121,11 +121,11 @@ //! //! ``` //! # #[macro_use] extern crate nix; -//! # #[cfg(any(target_os = "android", target_os = "linux"))] +//! # #[cfg(linux_android)] //! # use nix::libc::TCGETS as TCGETS; -//! # #[cfg(any(target_os = "android", target_os = "linux"))] +//! # #[cfg(linux_android)] //! # use nix::libc::termios as termios; -//! # #[cfg(any(target_os = "android", target_os = "linux"))] +//! # #[cfg(linux_android)] //! ioctl_read_bad!(tcgets, TCGETS, termios); //! # fn main() {} //! ``` @@ -179,9 +179,13 @@ //! # 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); +//! let res = unsafe { +//! 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() {} @@ -223,40 +227,18 @@ //! ``` use cfg_if::cfg_if; -#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))] +#[cfg(any(linux_android, target_os = "redox"))] #[macro_use] mod linux; -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "redox" -))] +#[cfg(any(linux_android, 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" -))] +#[cfg(any(bsd, solarish, target_os = "haiku",))] #[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" -))] +#[cfg(any(bsd, solarish, target_os = "haiku",))] pub use self::bsd::*; /// Convert raw ioctl return value to a Nix result @@ -305,7 +287,9 @@ macro_rules! ioctl_none { $(#[$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)) + unsafe { + convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type)) + } } ) } @@ -345,7 +329,9 @@ macro_rules! ioctl_none_bad { $(#[$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)) + unsafe { + convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type)) + } } ) } @@ -383,7 +369,9 @@ macro_rules! ioctl_read { 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)) + unsafe { + 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)) + } } ) } @@ -408,7 +396,7 @@ macro_rules! ioctl_read { /// /// ``` /// # #[macro_use] extern crate nix; -/// # #[cfg(any(target_os = "android", target_os = "linux"))] +/// # #[cfg(linux_android)] /// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios); /// # fn main() {} /// ``` @@ -419,7 +407,9 @@ macro_rules! ioctl_read_bad { 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)) + unsafe { + convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) + } } ) } @@ -456,7 +446,9 @@ macro_rules! ioctl_write_ptr { 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)) + unsafe { + 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)) + } } ) } @@ -481,7 +473,7 @@ macro_rules! ioctl_write_ptr { /// /// ``` /// # #[macro_use] extern crate nix; -/// # #[cfg(any(target_os = "android", target_os = "linux"))] +/// # #[cfg(linux_android)] /// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios); /// # fn main() {} /// ``` @@ -492,13 +484,15 @@ macro_rules! ioctl_write_ptr_bad { 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)) + unsafe { + 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"))] { + if #[cfg(freebsdlike)] { /// Generates a wrapper function for a ioctl that writes an integer to the kernel. /// /// The arguments to this macro are: @@ -533,7 +527,9 @@ cfg_if! { 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)) + unsafe { + convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data)) + } } ) } @@ -574,7 +570,9 @@ cfg_if! { 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)) + unsafe { + 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)) + } } ) } @@ -600,7 +598,7 @@ cfg_if! { /// /// ``` /// # #[macro_use] extern crate nix; -/// # #[cfg(any(target_os = "android", target_os = "linux"))] +/// # #[cfg(linux_android)] /// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK); /// # fn main() {} /// ``` @@ -618,7 +616,9 @@ macro_rules! ioctl_write_int_bad { 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)) + unsafe { + convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) + } } ) } @@ -655,7 +655,9 @@ macro_rules! ioctl_readwrite { 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)) + unsafe { + 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)) + } } ) } @@ -683,7 +685,9 @@ macro_rules! ioctl_readwrite_bad { 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)) + unsafe { + convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) + } } ) } @@ -712,7 +716,9 @@ macro_rules! ioctl_read_buf { 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_val(data)) as $crate::sys::ioctl::ioctl_num_type, data)) + unsafe { + convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data.as_mut_ptr())) + } } ) } @@ -751,7 +757,9 @@ macro_rules! ioctl_write_buf { 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, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data)) + unsafe { + convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data.as_ptr())) + } } ) } @@ -780,7 +788,9 @@ macro_rules! ioctl_readwrite_buf { 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_val(data)) as $crate::sys::ioctl::ioctl_num_type, data)) + unsafe { + convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of_val(data)) as $crate::sys::ioctl::ioctl_num_type, data.as_mut_ptr())) + } } ) } diff --git a/third_party/rust/nix/src/sys/memfd.rs b/third_party/rust/nix/src/sys/memfd.rs index 516ffd3262..22ee5fc5b7 100644 --- a/third_party/rust/nix/src/sys/memfd.rs +++ b/third_party/rust/nix/src/sys/memfd.rs @@ -29,6 +29,49 @@ libc_bitflags!( /// /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html MFD_ALLOW_SEALING; + /// Anonymous file will be created using huge pages. It should be safe now to + /// combine with [`MFD_ALLOW_SEALING`] too. + /// However, despite its presence, on FreeBSD it is unimplemented for now (ENOSYS). + /// + /// See also the hugetlb filesystem in [`memfd_create(2)`]. + /// + /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html + #[cfg(linux_android)] + MFD_HUGETLB; + /// Following are to be used with [`MFD_HUGETLB`], indicating the desired hugetlb size. + /// + /// See also the hugetlb filesystem in [`memfd_create(2)`]. + /// + /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html + #[cfg(linux_android)] + MFD_HUGE_1MB; + /// hugetlb size of 2MB. + #[cfg(linux_android)] + MFD_HUGE_2MB; + /// hugetlb size of 8MB. + #[cfg(linux_android)] + MFD_HUGE_8MB; + /// hugetlb size of 16MB. + #[cfg(linux_android)] + MFD_HUGE_16MB; + /// hugetlb size of 32MB. + #[cfg(linux_android)] + MFD_HUGE_32MB; + /// hugetlb size of 256MB. + #[cfg(linux_android)] + MFD_HUGE_256MB; + /// hugetlb size of 512MB. + #[cfg(linux_android)] + MFD_HUGE_512MB; + /// hugetlb size of 1GB. + #[cfg(linux_android)] + MFD_HUGE_1GB; + /// hugetlb size of 2GB. + #[cfg(linux_android)] + MFD_HUGE_2GB; + /// hugetlb size of 16GB. + #[cfg(linux_android)] + MFD_HUGE_16GB; } ); diff --git a/third_party/rust/nix/src/sys/mman.rs b/third_party/rust/nix/src/sys/mman.rs index 8cfd6d6d54..a64f14f588 100644 --- a/third_party/rust/nix/src/sys/mman.rs +++ b/third_party/rust/nix/src/sys/mman.rs @@ -8,7 +8,11 @@ use crate::Result; #[cfg(feature = "fs")] use crate::{fcntl::OFlag, sys::stat::Mode}; use libc::{self, c_int, c_void, off_t, size_t}; -use std::{num::NonZeroUsize, os::unix::io::{AsRawFd, AsFd}}; +use std::ptr::NonNull; +use std::{ + num::NonZeroUsize, + os::unix::io::{AsFd, AsRawFd}, +}; libc_bitflags! { /// Desired memory protection of a memory mapping. @@ -22,12 +26,10 @@ libc_bitflags! { /// 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] PROT_GROWSUP; } } @@ -45,145 +47,143 @@ libc_bitflags! { 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"), + #[cfg(any(all(linux_android, 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())))] + #[cfg(linux_android)] MAP_GROWSDOWN; /// Compatibility flag. Ignored. - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] MAP_DENYWRITE; /// Compatibility flag. Ignored. - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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", target_os = "aix")))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(not(any(freebsdlike, target_os = "aix", target_os = "hurd")))] MAP_NORESERVE; /// Populate page tables for a mapping. - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] MAP_NONBLOCK; /// Allocate the mapping using "huge pages." - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(freebsdlike)] 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())))] + #[cfg(netbsdlike)] 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())))] + #[cfg(any(freebsdlike, netbsdlike))] 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())))] + #[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))] 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())))] + #[cfg(apple_targets)] 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())))] + #[cfg(apple_targets)] 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; + /// Attempt to place the mapping at exactly the address specified in `addr`. + /// it's a default behavior on OpenBSD. + #[cfg(netbsdlike)] + MAP_TRYFIXED; + } +} + +impl MapFlags { + /// Create `MAP_HUGETLB` with provided size of huge page. + /// + /// Under the hood it computes `MAP_HUGETLB | (huge_page_size_log2 << libc::MAP_HUGE_SHIFT`). + /// `huge_page_size_log2` denotes logarithm of huge page size to use and should be + /// between 16 and 63 (inclusively). + /// + /// ``` + /// # use nix::sys::mman::MapFlags; + /// let f = MapFlags::map_hugetlb_with_size_log2(30).unwrap(); + /// assert_eq!(f, MapFlags::MAP_HUGETLB | MapFlags::MAP_HUGE_1GB); + /// ``` + #[cfg(any(linux_android, target_os = "fuchsia"))] + pub fn map_hugetlb_with_size_log2( + huge_page_size_log2: u32, + ) -> Option<Self> { + if (16..=63).contains(&huge_page_size_log2) { + let flag = libc::MAP_HUGETLB + | (huge_page_size_log2 << libc::MAP_HUGE_SHIFT) as i32; + Some(Self(flag.into())) + } else { + None + } } } @@ -193,19 +193,15 @@ libc_bitflags! { 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; } } @@ -228,30 +224,24 @@ libc_enum! { /// 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] MADV_DONTFORK, /// Undo the effect of `MADV_DONTFORK`. - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] MADV_MERGEABLE, /// Undo the effect of `MADV_MERGEABLE` - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] MADV_UNMERGEABLE, /// Preserve the memory of each page but offline the original page. #[cfg(any(target_os = "android", @@ -266,68 +256,52 @@ libc_enum! { 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())))] + #[cfg(linux_android)] MADV_HUGEPAGE, /// Undo the effect of `MADV_HUGEPAGE`. - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] MADV_NOHUGEPAGE, /// Exclude the given range from a core dump. - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] MADV_DONTDUMP, /// Undo the effect of an earlier `MADV_DONTDUMP`. - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] MADV_DODUMP, /// Specify that the application no longer needs the pages in the given range. - #[cfg(not(target_os = "aix"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(not(any(target_os = "aix", target_os = "hurd")))] 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())))] + #[cfg(freebsdlike)] 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())))] + #[cfg(freebsdlike)] MADV_AUTOSYNC, /// Region is not included in a core file. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(freebsdlike)] MADV_NOCORE, /// Include region in a core file - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(freebsdlike)] 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())))] + #[cfg(apple_targets)] MADV_ZERO_WIRED_PAGES, /// Pages can be reused (by anyone). - #[cfg(any(target_os = "ios", target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(apple_targets)] MADV_FREE_REUSABLE, /// Caller wants to reuse those pages. - #[cfg(any(target_os = "ios", target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(apple_targets)] 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())))] + #[cfg(apple_targets)] #[allow(missing_docs)] MADV_CAN_REUSE, } @@ -341,12 +315,10 @@ libc_bitflags! { /// 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())))] + #[cfg(apple_targets)] MS_KILLPAGES; /// Deactivate pages, but leave them mapped. - #[cfg(any(target_os = "ios", target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(apple_targets)] MS_DEACTIVATE; /// Perform an update and wait for it to complete. MS_SYNC; @@ -374,8 +346,8 @@ libc_bitflags! { /// `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) +pub unsafe fn mlock(addr: NonNull<c_void>, length: size_t) -> Result<()> { + unsafe { Errno::result(libc::mlock(addr.as_ptr(), length)).map(drop) } } /// Unlocks all memory pages that contain part of the address range with @@ -387,8 +359,8 @@ pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> { /// 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) +pub unsafe fn munlock(addr: NonNull<c_void>, length: size_t) -> Result<()> { + unsafe { Errno::result(libc::munlock(addr.as_ptr(), length)).map(drop) } } /// Locks all memory pages mapped into this process' address space. @@ -411,7 +383,9 @@ pub fn munlockall() -> Result<()> { unsafe { Errno::result(libc::munlockall()) }.map(drop) } -/// allocate memory, or map files or devices into memory +/// Allocate memory, or map files or devices into memory +/// +/// For anonymous mappings (`MAP_ANON`/`MAP_ANONYMOUS`), see [mmap_anonymous]. /// /// # Safety /// @@ -423,20 +397,54 @@ pub unsafe fn mmap<F: AsFd>( length: NonZeroUsize, prot: ProtFlags, flags: MapFlags, - f: Option<F>, + f: F, offset: off_t, -) -> Result<*mut c_void> { - let ptr = - addr.map_or(std::ptr::null_mut(), |a| usize::from(a) as *mut c_void); +) -> Result<NonNull<c_void>> { + let ptr = addr.map_or(std::ptr::null_mut(), |a| a.get() as *mut c_void); - let fd = f.map(|f| f.as_fd().as_raw_fd()).unwrap_or(-1); - let ret = - libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset); + let fd = f.as_fd().as_raw_fd(); + let ret = unsafe { + libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset) + }; + + if ret == libc::MAP_FAILED { + Err(Errno::last()) + } else { + // SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret` + // will be non-null here. + Ok(unsafe { NonNull::new_unchecked(ret) }) + } +} + +/// Create an anonymous memory mapping. +/// +/// This function is a wrapper around [`mmap`]: +/// `mmap(ptr, len, prot, MAP_ANONYMOUS | flags, -1, 0)`. +/// +/// # 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_anonymous( + addr: Option<NonZeroUsize>, + length: NonZeroUsize, + prot: ProtFlags, + flags: MapFlags, +) -> Result<NonNull<c_void>> { + let ptr = addr.map_or(std::ptr::null_mut(), |a| a.get() as *mut c_void); + + let flags = MapFlags::MAP_ANONYMOUS | flags; + let ret = unsafe { + libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), -1, 0) + }; if ret == libc::MAP_FAILED { Err(Errno::last()) } else { - Ok(ret) + // SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret` + // will be non-null here. + Ok(unsafe { NonNull::new_unchecked(ret) }) } } @@ -449,33 +457,43 @@ pub unsafe fn mmap<F: AsFd>( /// detailed requirements. #[cfg(any(target_os = "linux", target_os = "netbsd"))] pub unsafe fn mremap( - addr: *mut c_void, + addr: NonNull<c_void>, old_size: size_t, new_size: size_t, flags: MRemapFlags, - new_address: Option<*mut c_void>, -) -> Result<*mut c_void> { + new_address: Option<NonNull<c_void>>, +) -> Result<NonNull<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()), - ); + let ret = unsafe { + libc::mremap( + addr.as_ptr(), + old_size, + new_size, + flags.bits(), + new_address + .map(NonNull::as_ptr) + .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(), - ); + let ret = unsafe { + libc::mremap( + addr.as_ptr(), + old_size, + new_address + .map(NonNull::as_ptr) + .unwrap_or(std::ptr::null_mut()), + new_size, + flags.bits(), + ) + }; if ret == libc::MAP_FAILED { Err(Errno::last()) } else { - Ok(ret) + // SAFETY: `libc::mremap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret` + // will be non-null here. + Ok(unsafe { NonNull::new_unchecked(ret) }) } } @@ -487,8 +505,8 @@ pub unsafe fn mremap( /// 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) +pub unsafe fn munmap(addr: NonNull<c_void>, len: size_t) -> Result<()> { + unsafe { Errno::result(libc::munmap(addr.as_ptr(), len)).map(drop) } } /// give advice about use of memory @@ -499,12 +517,16 @@ pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> { /// [`MmapAdvise::MADV_FREE`]. /// /// [`madvise(2)`]: https://man7.org/linux/man-pages/man2/madvise.2.html +#[allow(rustdoc::broken_intra_doc_links)] // For Hurd as `MADV_FREE` is not available on it pub unsafe fn madvise( - addr: *mut c_void, + addr: NonNull<c_void>, length: size_t, advise: MmapAdvise, ) -> Result<()> { - Errno::result(libc::madvise(addr, length, advise as i32)).map(drop) + unsafe { + Errno::result(libc::madvise(addr.as_ptr(), length, advise as i32)) + .map(drop) + } } /// Set protection of memory mapping. @@ -519,27 +541,30 @@ pub unsafe fn madvise( /// /// ``` /// # use nix::libc::size_t; -/// # use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags}; +/// # use nix::sys::mman::{mmap_anonymous, mprotect, MapFlags, ProtFlags}; /// # use std::ptr; /// # use std::os::unix::io::BorrowedFd; /// 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::<BorrowedFd>(None, one_k_non_zero, ProtFlags::PROT_NONE, -/// MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, None, 0).unwrap(); +/// let mem = mmap_anonymous(None, one_k_non_zero, ProtFlags::PROT_NONE, MapFlags::MAP_PRIVATE) +/// .unwrap(); /// mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap(); -/// std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K) +/// std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K) /// }; /// assert_eq!(slice[0], 0x00); /// slice[0] = 0xFF; /// assert_eq!(slice[0], 0xFF); /// ``` pub unsafe fn mprotect( - addr: *mut c_void, + addr: NonNull<c_void>, length: size_t, prot: ProtFlags, ) -> Result<()> { - Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop) + unsafe { + Errno::result(libc::mprotect(addr.as_ptr(), length, prot.bits())) + .map(drop) + } } /// synchronize a mapped region @@ -551,11 +576,14 @@ pub unsafe fn mprotect( /// /// [`msync(2)`]: https://man7.org/linux/man-pages/man2/msync.2.html pub unsafe fn msync( - addr: *mut c_void, + addr: NonNull<c_void>, length: size_t, flags: MsFlags, ) -> Result<()> { - Errno::result(libc::msync(addr, length, flags.bits())).map(drop) + unsafe { + Errno::result(libc::msync(addr.as_ptr(), length, flags.bits())) + .map(drop) + } } #[cfg(not(target_os = "android"))] @@ -576,11 +604,11 @@ pub fn shm_open<P>( use std::os::unix::io::{FromRawFd, OwnedFd}; let ret = name.with_nix_path(|cstr| { - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] unsafe { libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint) } - #[cfg(not(any(target_os = "macos", target_os = "ios")))] + #[cfg(not(apple_targets))] unsafe { libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t) } diff --git a/third_party/rust/nix/src/sys/mod.rs b/third_party/rust/nix/src/sys/mod.rs index bf047b3dda..93339d1935 100644 --- a/third_party/rust/nix/src/sys/mod.rs +++ b/third_party/rust/nix/src/sys/mod.rs @@ -1,10 +1,8 @@ //! Mostly platform-specific functionality #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", + freebsdlike, all(target_os = "linux", not(target_env = "uclibc")), - target_os = "macos", + apple_targets, target_os = "netbsd" ))] feature! { @@ -15,41 +13,31 @@ feature! { feature! { #![feature = "event"] - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] #[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"))] + #[cfg(bsd)] pub mod event; - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(any(linux_android, target_os = "freebsd"))] #[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(target_os = "linux")] +feature! { + #![feature = "fanotify"] + pub mod fanotify; +} + +#[cfg(any(bsd, linux_android, target_os = "redox", solarish))] #[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"))] +#[cfg(any(linux_android, target_os = "freebsd"))] feature! { #![feature = "fs"] pub mod memfd; @@ -78,15 +66,7 @@ feature! { 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" -))] +#[cfg(any(linux_android, bsd))] feature! { #![feature = "ptrace"] #[allow(missing_docs)] @@ -99,7 +79,7 @@ feature! { pub mod quota; } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", netbsdlike))] feature! { #![feature = "reboot"] pub mod reboot; @@ -108,7 +88,7 @@ feature! { #[cfg(not(any( target_os = "redox", target_os = "fuchsia", - target_os = "illumos", + solarish, target_os = "haiku" )))] feature! { @@ -121,14 +101,7 @@ feature! { pub mod select; } -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos" -))] +#[cfg(any(linux_android, freebsdlike, apple_targets, solarish))] feature! { #![feature = "zerocopy"] pub mod sendfile; @@ -136,7 +109,7 @@ feature! { pub mod signal; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] feature! { #![feature = "signal"] #[allow(missing_docs)] @@ -155,15 +128,7 @@ feature! { 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" -))] +#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "openbsd"))] feature! { #![feature = "fs"] pub mod statfs; @@ -174,8 +139,7 @@ feature! { pub mod statvfs; } -#[cfg(any(target_os = "android", target_os = "linux"))] -#[cfg_attr(docsrs, doc(cfg(all())))] +#[cfg(linux_android)] #[allow(missing_docs)] pub mod sysinfo; @@ -203,13 +167,13 @@ feature! { pub mod wait; } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] feature! { #![feature = "inotify"] pub mod inotify; } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] feature! { #![feature = "time"] pub mod timerfd; @@ -218,7 +182,7 @@ feature! { #[cfg(all( any( target_os = "freebsd", - target_os = "illumos", + solarish, target_os = "linux", target_os = "netbsd" ), diff --git a/third_party/rust/nix/src/sys/personality.rs b/third_party/rust/nix/src/sys/personality.rs index 30231dd7b8..a4cfb5ef4f 100644 --- a/third_party/rust/nix/src/sys/personality.rs +++ b/third_party/rust/nix/src/sys/personality.rs @@ -21,7 +21,6 @@ libc_bitflags! { 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; @@ -43,7 +42,6 @@ libc_bitflags! { /// /// [`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; diff --git a/third_party/rust/nix/src/sys/prctl.rs b/third_party/rust/nix/src/sys/prctl.rs index 995382cb0c..42324beab2 100644 --- a/third_party/rust/nix/src/sys/prctl.rs +++ b/third_party/rust/nix/src/sys/prctl.rs @@ -50,7 +50,9 @@ pub fn get_child_subreaper() -> Result<bool> { // prctl writes into this var let mut subreaper: c_int = 0; - let res = unsafe { libc::prctl(libc::PR_GET_CHILD_SUBREAPER, &mut subreaper, 0, 0, 0) }; + let res = unsafe { + libc::prctl(libc::PR_GET_CHILD_SUBREAPER, &mut subreaper, 0, 0, 0) + }; Errno::result(res).map(|_| subreaper != 0) } @@ -78,7 +80,9 @@ pub fn get_keepcaps() -> Result<bool> { /// Clear the thread memory corruption kill policy and use the system-wide default pub fn clear_mce_kill() -> Result<()> { - let res = unsafe { libc::prctl(libc::PR_MCE_KILL, libc::PR_MCE_KILL_CLEAR, 0, 0, 0) }; + let res = unsafe { + libc::prctl(libc::PR_MCE_KILL, libc::PR_MCE_KILL_CLEAR, 0, 0, 0) + }; Errno::result(res).map(drop) } @@ -151,10 +155,11 @@ pub fn get_name() -> Result<CString> { let res = unsafe { libc::prctl(libc::PR_GET_NAME, &buf, 0, 0, 0) }; - let len = buf.iter().position(|&c| c == 0).unwrap_or(buf.len()); - let name = CStr::from_bytes_with_nul(&buf[..=len]).map_err(|_| Errno::EINVAL)?; - - Errno::result(res).map(|_| name.to_owned()) + Errno::result(res).and_then(|_| { + CStr::from_bytes_until_nul(&buf) + .map(CStr::to_owned) + .map_err(|_| Errno::EINVAL) + }) } /// Sets the timer slack value for the calling thread. Timer slack is used by the kernel to group @@ -174,14 +179,16 @@ pub fn get_timerslack() -> Result<i32> { /// Disable all performance counters attached to the calling process. pub fn task_perf_events_disable() -> Result<()> { - let res = unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_DISABLE, 0, 0, 0, 0) }; + let res = + unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_DISABLE, 0, 0, 0, 0) }; Errno::result(res).map(drop) } /// Enable all performance counters attached to the calling process. pub fn task_perf_events_enable() -> Result<()> { - let res = unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_ENABLE, 0, 0, 0, 0) }; + let res = + unsafe { libc::prctl(libc::PR_TASK_PERF_EVENTS_ENABLE, 0, 0, 0, 0) }; Errno::result(res).map(drop) } diff --git a/third_party/rust/nix/src/sys/ptrace/bsd.rs b/third_party/rust/nix/src/sys/ptrace/bsd.rs index ba267c6577..3dd486210c 100644 --- a/third_party/rust/nix/src/sys/ptrace/bsd.rs +++ b/third_party/rust/nix/src/sys/ptrace/bsd.rs @@ -9,10 +9,7 @@ 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"))] { + if #[cfg(any(freebsdlike, apple_targets, target_os = "openbsd"))] { #[doc(hidden)] pub type AddressType = *mut ::libc::c_char; } else { @@ -29,33 +26,26 @@ libc_enum! { PT_TRACE_ME, PT_READ_I, PT_READ_D, - #[cfg(target_os = "macos")] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(apple_targets)] PT_READ_U, PT_WRITE_I, PT_WRITE_D, - #[cfg(target_os = "macos")] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(apple_targets)] PT_WRITE_U, PT_CONTINUE, PT_KILL, - #[cfg(any(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos"), + #[cfg(any(any(freebsdlike, apple_targets), 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())))] + #[cfg(apple_targets)] PT_SIGEXC, - #[cfg(target_os = "macos")] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(apple_targets)] PT_THUPDATE, - #[cfg(target_os = "macos")] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(apple_targets)] PT_ATTACHEXC } } @@ -66,13 +56,15 @@ unsafe fn ptrace_other( addr: AddressType, data: c_int, ) -> Result<c_int> { - Errno::result(libc::ptrace( - request as RequestType, - libc::pid_t::from(pid), - addr, - data, - )) - .map(|_| 0) + unsafe { + 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, ...)` @@ -157,7 +149,7 @@ pub fn kill(pid: Pid) -> Result<()> { /// } /// ``` #[cfg(any( - any(target_os = "dragonfly", target_os = "freebsd", target_os = "macos"), + any(freebsdlike, apple_targets), all(target_os = "openbsd", target_arch = "x86_64"), all( target_os = "netbsd", diff --git a/third_party/rust/nix/src/sys/ptrace/linux.rs b/third_party/rust/nix/src/sys/ptrace/linux.rs index 8c134cf7ee..26544e134b 100644 --- a/third_party/rust/nix/src/sys/ptrace/linux.rs +++ b/third_party/rust/nix/src/sys/ptrace/linux.rs @@ -53,28 +53,36 @@ libc_enum! { #[cfg(any(all(target_os = "android", target_pointer_width = "32"), all(target_os = "linux", any(target_env = "musl", target_arch = "mips", + target_arch = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", 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 = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", 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 = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", 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 = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "x86_64", target_pointer_width = "32"))))] PTRACE_SETFPREGS, @@ -82,13 +90,17 @@ libc_enum! { PTRACE_DETACH, #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "mips", + target_arch = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "x86", target_arch = "x86_64")))] PTRACE_GETFPXREGS, #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "mips", + target_arch = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "x86", target_arch = "x86_64")))] PTRACE_SETFPXREGS, @@ -98,22 +110,28 @@ libc_enum! { PTRACE_GETSIGINFO, PTRACE_SETSIGINFO, #[cfg(all(target_os = "linux", not(any(target_arch = "mips", - target_arch = "mips64"))))] + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6"))))] PTRACE_GETREGSET, #[cfg(all(target_os = "linux", not(any(target_arch = "mips", - target_arch = "mips64"))))] + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6"))))] 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"))))] + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6"))))] PTRACE_LISTEN, #[cfg(all(target_os = "linux", not(any(target_arch = "mips", - target_arch = "mips64"))))] + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6"))))] PTRACE_PEEKSIGINFO, #[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))] @@ -241,13 +259,13 @@ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> { /// 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 mut data = mem::MaybeUninit::<T>::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, + data.as_mut_ptr(), ) }; Errno::result(res)?; @@ -260,13 +278,15 @@ unsafe fn ptrace_other( 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) + unsafe { + Errno::result(libc::ptrace( + request as RequestType, + libc::pid_t::from(pid), + addr, + data, + )) + .map(|_| 0) + } } /// Set options, as with `ptrace(PTRACE_SETOPTIONS, ...)`. @@ -381,7 +401,6 @@ pub fn attach(pid: Pid) -> Result<()> { /// /// 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( @@ -428,7 +447,6 @@ pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> { /// /// 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( @@ -535,7 +553,7 @@ pub unsafe fn write( addr: AddressType, data: *mut c_void, ) -> Result<()> { - ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop) + unsafe { ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop) } } /// Reads a word from a user area at `offset`, as with ptrace(PTRACE_PEEKUSER, ...). @@ -556,5 +574,7 @@ pub unsafe fn write_user( offset: AddressType, data: *mut c_void, ) -> Result<()> { - ptrace_other(Request::PTRACE_POKEUSER, pid, offset, data).map(drop) + unsafe { + ptrace_other(Request::PTRACE_POKEUSER, pid, offset, data).map(drop) + } } diff --git a/third_party/rust/nix/src/sys/ptrace/mod.rs b/third_party/rust/nix/src/sys/ptrace/mod.rs index 88648acabc..c059797df9 100644 --- a/third_party/rust/nix/src/sys/ptrace/mod.rs +++ b/third_party/rust/nix/src/sys/ptrace/mod.rs @@ -1,25 +1,13 @@ //! Provides helpers for making ptrace system calls -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] mod linux; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] pub use self::linux::*; -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" -))] +#[cfg(bsd)] mod bsd; -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" -))] +#[cfg(bsd)] pub use self::bsd::*; diff --git a/third_party/rust/nix/src/sys/quota.rs b/third_party/rust/nix/src/sys/quota.rs index a32d07aa1e..2d12b858bf 100644 --- a/third_party/rust/nix/src/sys/quota.rs +++ b/third_party/rust/nix/src/sys/quota.rs @@ -264,7 +264,7 @@ pub fn quotactl_on<P: ?Sized + NixPath>( ) -> 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; + let p: *mut c_char = path_copy.as_mut_ptr().cast(); quotactl( QuotaCmd(QuotaSubCmd::Q_QUOTAON, which), Some(special), @@ -308,12 +308,12 @@ pub fn quotactl_get<P: ?Sized + NixPath>( special: &P, id: c_int, ) -> Result<Dqblk> { - let mut dqblk = mem::MaybeUninit::uninit(); + let mut dqblk = mem::MaybeUninit::<libc::dqblk>::uninit(); quotactl( QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, - dqblk.as_mut_ptr() as *mut c_char, + dqblk.as_mut_ptr().cast(), )?; Ok(unsafe { Dqblk(dqblk.assume_init()) }) } diff --git a/third_party/rust/nix/src/sys/reboot.rs b/third_party/rust/nix/src/sys/reboot.rs index 02d98162bd..2e4d888de4 100644 --- a/third_party/rust/nix/src/sys/reboot.rs +++ b/third_party/rust/nix/src/sys/reboot.rs @@ -1,48 +1,141 @@ -//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete. +//! Reboot/shutdown +//! +//! On Linux, This can also be used to enable/disable Ctrl-Alt-Delete. use crate::errno::Errno; use crate::Result; +use cfg_if::cfg_if; 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()) -} +cfg_if! { + if #[cfg(target_os = "linux")] { + 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) + /// 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) + } + } else if #[cfg(netbsdlike)] { + use libc::c_int; + + libc_bitflags! { + /// How exactly should the system be rebooted. + pub struct RebootMode: c_int { + /// The default, causing the system to reboot in its usual fashion. + RB_AUTOBOOT; + /// Interpreted by the bootstrap program itself, causing it to + /// prompt on the console as to what file should be booted. + /// Normally, the system is booted from the file “xx(0,0)bsd”, + /// where xx is the default disk name, without prompting for + /// the file name. + RB_ASKNAME; + /// Dump kernel memory before rebooting; see `savecore(8)` for + /// more information. + RB_DUMP; + /// The processor is simply halted; no reboot takes place. + RB_HALT; + /// Power off the system if the system hardware supports the + /// function, otherwise it has no effect. + /// + /// Should be used in conjunction with `RB_HALT`. + RB_POWERDOWN; + /// By default, the system will halt if `reboot()` is called during + /// startup (before the system has finished autoconfiguration), even + /// if `RB_HALT` is not specified. This is because `panic(9)`s + /// during startup will probably just repeat on the next boot. + /// Use of this option implies that the user has requested the + /// action specified (for example, using the `ddb(4)` boot reboot + /// command), so the system will reboot if a halt is not explicitly + /// requested. + #[cfg(target_os = "openbsd")] + RB_USERREQ; + /// Load the symbol table and enable a built-in debugger in the + /// system. This option will have no useful function if the kernel + /// is not configured for debugging. Several other options have + /// different meaning if combined with this option, although their + /// use may not be possible via the `reboot()` call. See `ddb(4)` for + /// more information. + RB_KDB; + /// Normally, the disks are sync'd (see `sync(8)`) before the + /// processor is halted or rebooted. This option may be useful + /// if file system changes have been made manually or if the + /// processor is on fire. + RB_NOSYNC; + /// Normally, the reboot procedure involves an automatic disk + /// consistency check and then multi-user operations. `RB_SINGLE` + /// prevents this, booting the system with a single-user shell on + /// the console. `RB_SINGLE` is actually interpreted by the `init(8)` + /// program in the newly booted system. + /// + /// When no options are given (i.e., `RB_AUTOBOOT` is used), the + /// system is rebooted from file /bsd in the root file system of + /// unit 0 of a disk chosen in a processor specific way. An automatic + /// consistency check of the disks is normally performed (see `fsck(8)`). + RB_SINGLE; + /// Initially invoke the `userconf(4)` facility when the system + /// starts up again, if it has been compiled into the kernel + /// that is loaded. + #[cfg(target_os = "netbsd")] + RB_USERCONF; + /// Don't update the hardware clock from the system clock, presumably + /// because the system clock is suspect. + #[cfg(target_os = "openbsd")] + RB_TIMEBAD; + } + } + + /// Reboot system or halt processor + /// + /// For more information, see the man pages: + /// + /// * [NetBSD](https://man.netbsd.org/reboot.2) + /// * [OpenBSD](https://man.openbsd.org/reboot.2) + #[cfg(netbsdlike)] + pub fn reboot(how: RebootMode) -> Result<Infallible> { + #[cfg(target_os = "openbsd")] + unsafe { libc::reboot(how.bits()) }; + #[cfg(target_os = "netbsd")] + unsafe { libc::reboot(how.bits(), std::ptr::null_mut()) }; + + Err(Errno::last()) + } + } } + diff --git a/third_party/rust/nix/src/sys/resource.rs b/third_party/rust/nix/src/sys/resource.rs index f42d32e3ca..71315072d4 100644 --- a/third_party/rust/nix/src/sys/resource.rs +++ b/third_party/rust/nix/src/sys/resource.rs @@ -10,16 +10,14 @@ pub use libc::RLIM_INFINITY; use std::mem; cfg_if! { - if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ + if #[cfg(any( + all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), + target_os = "hurd" + ))]{ 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", + bsd, target_os = "android", - target_os = "dragonfly", target_os = "aix", all(target_os = "linux", not(target_env = "gnu")) ))]{ @@ -43,22 +41,19 @@ libc_enum! { // // 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", + all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), + target_os = "hurd" + ), repr(u32))] + #[cfg_attr(any( + bsd, target_os = "android", - target_os = "dragonfly", target_os = "aix", 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())))] + #[cfg(not(any(target_os = "freebsd", netbsdlike)))] /// The maximum amount (in bytes) of virtual memory the process is /// allowed to map. RLIMIT_AS, @@ -77,102 +72,78 @@ libc_enum! { 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())))] + #[cfg(linux_android)] /// 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())))] + #[cfg(any(linux_android, target_os = "freebsd", netbsdlike))] /// 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())))] + #[cfg(linux_android)] /// 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())))] + #[cfg(linux_android)] /// A ceiling to which the process's nice value can be raised using /// setpriority or nice. RLIMIT_NICE, #[cfg(any( - target_os = "android", + linux_android, target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd", - target_os = "linux", + netbsdlike, target_os = "aix", ))] - #[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", + #[cfg(any(linux_android, target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd", - target_os = "linux", + netbsdlike, target_os = "aix", ))] - #[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())))] + #[cfg(linux_android)] /// 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())))] + #[cfg(linux_android)] /// 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())))] + #[cfg(freebsdlike)] /// 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, } @@ -206,7 +177,10 @@ 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")))]{ + if #[cfg(any( + all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), + target_os = "hurd" + ))] { 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()) }; @@ -259,7 +233,10 @@ pub fn setrlimit( rlim_max: hard_limit, }; cfg_if! { - if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ + if #[cfg(any( + all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), + target_os = "hurd", + ))]{ 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) }; @@ -281,7 +258,6 @@ libc_enum! { 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, } @@ -420,28 +396,3 @@ pub fn getrusage(who: UsageWho) -> Result<Usage> { 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/third_party/rust/nix/src/sys/select.rs b/third_party/rust/nix/src/sys/select.rs index 0e2193b130..64a8e258cf 100644 --- a/third_party/rust/nix/src/sys/select.rs +++ b/third_party/rust/nix/src/sys/select.rs @@ -7,7 +7,7 @@ use std::convert::TryFrom; use std::iter::FusedIterator; use std::mem; use std::ops::Range; -use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; +use std::os::unix::io::{AsRawFd, BorrowedFd, RawFd}; use std::ptr::{null, null_mut}; pub use libc::FD_SETSIZE; @@ -41,21 +41,21 @@ impl<'fd> FdSet<'fd> { } /// Add a file descriptor to an `FdSet` - pub fn insert<Fd: AsFd>(&mut self, fd: &'fd Fd) { - assert_fd_valid(fd.as_fd().as_raw_fd()); - unsafe { libc::FD_SET(fd.as_fd().as_raw_fd(), &mut self.set) }; + pub fn insert(&mut self, fd: BorrowedFd<'fd>) { + assert_fd_valid(fd.as_raw_fd()); + unsafe { libc::FD_SET(fd.as_raw_fd(), &mut self.set) }; } /// Remove a file descriptor from an `FdSet` - pub fn remove<Fd: AsFd>(&mut self, fd: &'fd Fd) { - assert_fd_valid(fd.as_fd().as_raw_fd()); - unsafe { libc::FD_CLR(fd.as_fd().as_raw_fd(), &mut self.set) }; + pub fn remove(&mut self, fd: BorrowedFd<'fd>) { + assert_fd_valid(fd.as_raw_fd()); + unsafe { libc::FD_CLR(fd.as_raw_fd(), &mut self.set) }; } /// Test an `FdSet` for the presence of a certain file descriptor. - pub fn contains<Fd: AsFd>(&self, fd: &'fd Fd) -> bool { - assert_fd_valid(fd.as_fd().as_raw_fd()); - unsafe { libc::FD_ISSET(fd.as_fd().as_raw_fd(), &self.set) } + pub fn contains(&self, fd: BorrowedFd<'fd>) -> bool { + assert_fd_valid(fd.as_raw_fd()); + unsafe { libc::FD_ISSET(fd.as_raw_fd(), &self.set) } } /// Remove all file descriptors from this `FdSet`. @@ -77,8 +77,8 @@ impl<'fd> FdSet<'fd> { /// let fd_four = unsafe {BorrowedFd::borrow_raw(4)}; /// let fd_nine = unsafe {BorrowedFd::borrow_raw(9)}; /// let mut set = FdSet::new(); - /// set.insert(&fd_four); - /// set.insert(&fd_nine); + /// set.insert(fd_four); + /// set.insert(fd_nine); /// assert_eq!(set.highest().map(|borrowed_fd|borrowed_fd.as_raw_fd()), Some(9)); /// ``` /// @@ -101,8 +101,8 @@ impl<'fd> FdSet<'fd> { /// let mut set = FdSet::new(); /// let fd_four = unsafe {BorrowedFd::borrow_raw(4)}; /// let fd_nine = unsafe {BorrowedFd::borrow_raw(9)}; - /// set.insert(&fd_four); - /// set.insert(&fd_nine); + /// set.insert(fd_four); + /// set.insert(fd_nine); /// let fds: Vec<RawFd> = set.fds(None).map(|borrowed_fd|borrowed_fd.as_raw_fd()).collect(); /// assert_eq!(fds, vec![4, 9]); /// ``` @@ -134,7 +134,7 @@ impl<'a, 'fd> Iterator for Fds<'a, 'fd> { fn next(&mut self) -> Option<Self::Item> { for i in &mut self.range { let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - if self.set.contains(&borrowed_i) { + if self.set.contains(borrowed_i) { return Some(borrowed_i); } } @@ -153,7 +153,7 @@ impl<'a, 'fd> DoubleEndedIterator for Fds<'a, 'fd> { fn next_back(&mut self) -> Option<BorrowedFd<'fd>> { while let Some(i) = self.range.next_back() { let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - if self.set.contains(&borrowed_i) { + if self.set.contains(borrowed_i) { return Some(borrowed_i); } } @@ -317,238 +317,3 @@ where Errno::result(res) } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::sys::time::{TimeVal, TimeValLike}; - use crate::unistd::{close, pipe, write}; - use std::os::unix::io::{FromRawFd, OwnedFd, RawFd}; - - #[test] - fn fdset_insert() { - let mut fd_set = FdSet::new(); - - for i in 0..FD_SETSIZE { - let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - assert!(!fd_set.contains(&borrowed_i)); - } - - let fd_seven = unsafe { BorrowedFd::borrow_raw(7) }; - fd_set.insert(&fd_seven); - - assert!(fd_set.contains(&fd_seven)); - } - - #[test] - fn fdset_remove() { - let mut fd_set = FdSet::new(); - - for i in 0..FD_SETSIZE { - let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - assert!(!fd_set.contains(&borrowed_i)); - } - - let fd_seven = unsafe { BorrowedFd::borrow_raw(7) }; - fd_set.insert(&fd_seven); - fd_set.remove(&fd_seven); - - for i in 0..FD_SETSIZE { - let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - assert!(!fd_set.contains(&borrowed_i)); - } - } - - #[test] - #[allow(non_snake_case)] - fn fdset_clear() { - let mut fd_set = FdSet::new(); - let fd_one = unsafe { BorrowedFd::borrow_raw(1) }; - let fd_FD_SETSIZE_devided_by_two = - unsafe { BorrowedFd::borrow_raw((FD_SETSIZE / 2) as RawFd) }; - let fd_FD_SETSIZE_minus_one = - unsafe { BorrowedFd::borrow_raw((FD_SETSIZE - 1) as RawFd) }; - fd_set.insert(&fd_one); - fd_set.insert(&fd_FD_SETSIZE_devided_by_two); - fd_set.insert(&fd_FD_SETSIZE_minus_one); - - fd_set.clear(); - - for i in 0..FD_SETSIZE { - let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) }; - assert!(!fd_set.contains(&borrowed_i)); - } - } - - #[test] - fn fdset_highest() { - let mut set = FdSet::new(); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - None - ); - let fd_zero = unsafe { BorrowedFd::borrow_raw(0) }; - let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) }; - set.insert(&fd_zero); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - Some(0) - ); - set.insert(&fd_ninety); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - Some(90) - ); - set.remove(&fd_zero); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - Some(90) - ); - set.remove(&fd_ninety); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - None - ); - - let fd_four = unsafe { BorrowedFd::borrow_raw(4) }; - let fd_five = unsafe { BorrowedFd::borrow_raw(5) }; - let fd_seven = unsafe { BorrowedFd::borrow_raw(7) }; - set.insert(&fd_four); - set.insert(&fd_five); - set.insert(&fd_seven); - assert_eq!( - set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()), - Some(7) - ); - } - - #[test] - fn fdset_fds() { - let mut set = FdSet::new(); - let fd_zero = unsafe { BorrowedFd::borrow_raw(0) }; - let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) }; - assert_eq!( - set.fds(None) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::<Vec<_>>(), - vec![] - ); - set.insert(&fd_zero); - assert_eq!( - set.fds(None) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::<Vec<_>>(), - vec![0] - ); - set.insert(&fd_ninety); - assert_eq!( - set.fds(None) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::<Vec<_>>(), - vec![0, 90] - ); - - // highest limit - assert_eq!( - set.fds(Some(89)) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::<Vec<_>>(), - vec![0] - ); - assert_eq!( - set.fds(Some(90)) - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .collect::<Vec<_>>(), - vec![0, 90] - ); - } - - #[test] - fn test_select() { - let (r1, w1) = pipe().unwrap(); - let r1 = unsafe { OwnedFd::from_raw_fd(r1) }; - let w1 = unsafe { OwnedFd::from_raw_fd(w1) }; - let (r2, _w2) = pipe().unwrap(); - let r2 = unsafe { OwnedFd::from_raw_fd(r2) }; - - write(w1.as_raw_fd(), b"hi!").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)); - close(_w2).unwrap(); - } - - #[test] - fn test_select_nfds() { - let (r1, w1) = pipe().unwrap(); - let (r2, _w2) = pipe().unwrap(); - let r1 = unsafe { OwnedFd::from_raw_fd(r1) }; - let w1 = unsafe { OwnedFd::from_raw_fd(w1) }; - let r2 = unsafe { OwnedFd::from_raw_fd(r2) }; - - write(w1.as_raw_fd(), b"hi!").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() - .map(|borrowed_fd| borrowed_fd.as_raw_fd()) - .unwrap() - + 1 - ), - &mut fd_set, - None, - None, - &mut timeout - ) - .unwrap() - ); - } - assert!(fd_set.contains(&r1)); - assert!(!fd_set.contains(&r2)); - close(_w2).unwrap(); - } - - #[test] - fn test_select_nfds2() { - let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let (r2, _w2) = pipe().unwrap(); - let r1 = unsafe { OwnedFd::from_raw_fd(r1) }; - let r2 = unsafe { OwnedFd::from_raw_fd(r2) }; - 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.as_raw_fd(), r2.as_raw_fd()) + 1, - &mut fd_set, - None, - None, - &mut timeout - ) - .unwrap() - ); - assert!(fd_set.contains(&r1)); - assert!(!fd_set.contains(&r2)); - close(_w2).unwrap(); - } -} diff --git a/third_party/rust/nix/src/sys/sendfile.rs b/third_party/rust/nix/src/sys/sendfile.rs index 9f3c333f97..d7452edd7c 100644 --- a/third_party/rust/nix/src/sys/sendfile.rs +++ b/third_party/rust/nix/src/sys/sendfile.rs @@ -20,9 +20,9 @@ use crate::Result; /// /// `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())))] +/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html) for Linux, +/// see [the sendfile(2) man page.](https://docs.oracle.com/cd/E88353_01/html/E37843/sendfile-3c.html) for Solaris. +#[cfg(any(linux_android, solarish))] pub fn sendfile<F1: AsFd, F2: AsFd>( out_fd: F1, in_fd: F2, @@ -56,7 +56,6 @@ pub fn sendfile<F1: AsFd, F2: AsFd>( /// /// 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<F1: AsFd, F2: AsFd>( out_fd: F1, in_fd: F2, @@ -78,46 +77,82 @@ pub fn sendfile64<F1: AsFd, F2: AsFd>( } cfg_if! { - if #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos"))] { + if #[cfg(any(freebsdlike, apple_targets))] { use std::io::IoSlice; #[derive(Clone, Debug)] - struct SendfileHeaderTrailer<'a>( - libc::sf_hdtr, - Option<Vec<IoSlice<'a>>>, - Option<Vec<IoSlice<'a>>>, - ); + struct SendfileHeaderTrailer<'a> { + raw: libc::sf_hdtr, + _headers: Option<Vec<IoSlice<'a>>>, + _trailers: 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<'_>>> = + let mut header_iovecs: Option<Vec<IoSlice<'_>>> = headers.map(|s| s.iter().map(|b| IoSlice::new(b)).collect()); - let trailer_iovecs: Option<Vec<IoSlice<'_>>> = + let mut trailer_iovecs: Option<Vec<IoSlice<'_>>> = trailers.map(|s| s.iter().map(|b| IoSlice::new(b)).collect()); - SendfileHeaderTrailer( - libc::sf_hdtr { + + SendfileHeaderTrailer { + raw: libc::sf_hdtr { headers: { header_iovecs - .as_ref() - .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec + .as_mut() + .map_or(ptr::null_mut(), |v| v.as_mut_ptr()) + .cast() }, 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 + .as_mut() + .map_or(ptr::null_mut(), |v| v.as_mut_ptr()) + .cast() }, trl_cnt: trailer_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32 }, - header_iovecs, - trailer_iovecs, - ) + _headers: header_iovecs, + _trailers: trailer_iovecs, + } + } + } + } else if #[cfg(solarish)] { + use std::os::unix::io::BorrowedFd; + use std::marker::PhantomData; + + #[derive(Debug, Copy, Clone)] + /// Mapping of the raw C sendfilevec_t struct + pub struct SendfileVec<'fd> { + raw: libc::sendfilevec_t, + phantom: PhantomData<BorrowedFd<'fd>> + } + + impl<'fd> SendfileVec<'fd> { + /// initialises SendfileVec to send data directly from the process's address space + /// same in C with sfv_fd set to SFV_FD_SELF. + pub fn newself( + off: off_t, + len: usize + ) -> Self { + Self{raw: libc::sendfilevec_t{sfv_fd: libc::SFV_FD_SELF, sfv_flag: 0, sfv_off: off, sfv_len: len}, phantom: PhantomData} + } + + /// initialises SendfileVec to send data from `fd`. + pub fn new( + fd: BorrowedFd<'fd>, + off: off_t, + len: usize + ) -> SendfileVec<'fd> { + Self{raw: libc::sendfilevec_t{sfv_fd: fd.as_raw_fd(), sfv_flag: 0, sfv_off:off, sfv_len: len}, phantom: PhantomData} + } + } + + impl From<SendfileVec<'_>> for libc::sendfilevec_t { + fn from<'fd>(vec: SendfileVec) -> libc::sendfilevec_t { + vec.raw } } } @@ -187,7 +222,7 @@ cfg_if! { 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 hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.raw as *const libc::sf_hdtr); let return_code = unsafe { libc::sendfile(in_fd.as_fd().as_raw_fd(), out_sock.as_fd().as_raw_fd(), @@ -230,7 +265,7 @@ cfg_if! { ) -> (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 hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.raw as *const libc::sf_hdtr); let return_code = unsafe { libc::sendfile(in_fd.as_fd().as_raw_fd(), out_sock.as_fd().as_raw_fd(), @@ -242,7 +277,7 @@ cfg_if! { }; (Errno::result(return_code).and(Ok(())), bytes_sent) } - } else if #[cfg(any(target_os = "ios", target_os = "macos"))] { + } else if #[cfg(apple_targets)] { /// Read bytes from `in_fd` starting at `offset` and write up to `count` bytes to /// `out_sock`. /// @@ -276,7 +311,7 @@ cfg_if! { ) -> (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 hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.raw as *const libc::sf_hdtr); let return_code = unsafe { libc::sendfile(in_fd.as_fd().as_raw_fd(), out_sock.as_fd().as_raw_fd(), @@ -287,5 +322,30 @@ cfg_if! { }; (Errno::result(return_code).and(Ok(())), len) } + } else if #[cfg(solarish)] { + /// Write data from the vec arrays to `out_sock` and returns a `Result` and a + /// count of bytes written. + /// + /// Each `SendfileVec` set needs to be instantiated either with `SendfileVec::new` or + /// `SendfileVec::newself`. + /// + /// The former allows to send data from a file descriptor through `fd`, + /// from an offset `off` and for a given amount of data `len`. + /// + /// The latter allows to send data from the process's address space, from an offset `off` + /// and for a given amount of data `len`. + /// + /// For more information, see + /// [the sendfilev(3) man page.](https://illumos.org/man/3EXT/sendfilev) + pub fn sendfilev<F: AsFd>( + out_sock: F, + vec: &[SendfileVec] + ) -> (Result<()>, usize) { + let mut len = 0usize; + let return_code = unsafe { + libc::sendfilev(out_sock.as_fd().as_raw_fd(), vec.as_ptr() as *const libc::sendfilevec_t, vec.len() as i32, &mut len) + }; + (Errno::result(return_code).and(Ok(())), len) + } } } diff --git a/third_party/rust/nix/src/sys/signal.rs b/third_party/rust/nix/src/sys/signal.rs index c946e4a0b1..c9b593d0db 100644 --- a/third_party/rust/nix/src/sys/signal.rs +++ b/third_party/rust/nix/src/sys/signal.rs @@ -7,14 +7,17 @@ use crate::errno::Errno; use crate::{Error, Result}; use cfg_if::cfg_if; use std::fmt; +use std::hash::{Hash, Hasher}; use std::mem; -#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] +use std::ops::BitOr; +#[cfg(freebsdlike)] use std::os::unix::io::RawFd; use std::ptr; use std::str::FromStr; #[cfg(not(any( target_os = "fuchsia", + target_os = "hurd", target_os = "openbsd", target_os = "redox" )))] @@ -63,9 +66,12 @@ libc_enum! { /// 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", + #[cfg(all(any(linux_android, target_os = "emscripten", + target_os = "fuchsia"), + not(any(target_arch = "mips", + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6", target_arch = "sparc64"))))] SIGSTKFLT, /// To parent on child stop or exit @@ -94,27 +100,21 @@ libc_enum! { 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", - target_os = "aix"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(any(linux_android, target_os = "emscripten", + target_os = "fuchsia", target_os = "aix"))] /// Power failure imminent. SIGPWR, /// Bad system call SIGSYS, - #[cfg(not(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux", + #[cfg(not(any(linux_android, target_os = "emscripten", + target_os = "fuchsia", 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", - target_os = "aix")))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(not(any(linux_android, target_os = "emscripten", + target_os = "fuchsia", target_os = "redox", + target_os = "haiku", target_os = "aix")))] /// Information request SIGINFO, } @@ -143,14 +143,15 @@ impl FromStr for Signal { "SIGTERM" => Signal::SIGTERM, #[cfg(all( any( - target_os = "android", + linux_android, target_os = "emscripten", target_os = "fuchsia", - target_os = "linux" ), not(any( target_arch = "mips", + target_arch = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "sparc64" )) ))] @@ -170,27 +171,24 @@ impl FromStr for Signal { #[cfg(not(target_os = "haiku"))] "SIGIO" => Signal::SIGIO, #[cfg(any( - target_os = "android", + linux_android, target_os = "emscripten", target_os = "fuchsia", - target_os = "linux" ))] "SIGPWR" => Signal::SIGPWR, "SIGSYS" => Signal::SIGSYS, #[cfg(not(any( - target_os = "android", + linux_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", + linux_android, target_os = "emscripten", target_os = "fuchsia", - target_os = "linux", target_os = "redox", target_os = "aix", target_os = "haiku" @@ -227,14 +225,15 @@ impl Signal { Signal::SIGTERM => "SIGTERM", #[cfg(all( any( - target_os = "android", + linux_android, target_os = "emscripten", target_os = "fuchsia", - target_os = "linux" ), not(any( target_arch = "mips", + target_arch = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "sparc64" )) ))] @@ -254,28 +253,25 @@ impl Signal { #[cfg(not(target_os = "haiku"))] Signal::SIGIO => "SIGIO", #[cfg(any( - target_os = "android", + linux_android, target_os = "emscripten", target_os = "fuchsia", target_os = "aix", - target_os = "linux" ))] Signal::SIGPWR => "SIGPWR", Signal::SIGSYS => "SIGSYS", #[cfg(not(any( - target_os = "android", + linux_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", + linux_android, target_os = "emscripten", target_os = "fuchsia", - target_os = "linux", target_os = "redox", target_os = "aix", target_os = "haiku" @@ -319,15 +315,12 @@ const SIGNALS: [Signal; 28] = [ SIGPROF, SIGWINCH, SIGSYS, ]; #[cfg(all( - any( - target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia" - ), + any(linux_android, target_os = "emscripten", target_os = "fuchsia"), not(any( target_arch = "mips", + target_arch = "mips32r6", target_arch = "mips64", + target_arch = "mips64r6", target_arch = "sparc64" )) ))] @@ -339,13 +332,14 @@ const SIGNALS: [Signal; 31] = [ SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS, ]; #[cfg(all( + any(linux_android, target_os = "emscripten", target_os = "fuchsia"), any( - target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia" - ), - any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64") + target_arch = "mips", + target_arch = "mips32r6", + target_arch = "mips64", + target_arch = "mips64r6", + target_arch = "sparc64" + ) ))] #[cfg(feature = "signal")] const SIGNALS: [Signal; 30] = [ @@ -363,8 +357,7 @@ const SIGNALS: [Signal; 30] = [ SIGVTALRM, SIGPROF, SIGXCPU, SIGXFSZ, SIGTRAP, ]; #[cfg(not(any( - target_os = "linux", - target_os = "android", + linux_android, target_os = "fuchsia", target_os = "emscripten", target_os = "aix", @@ -439,6 +432,7 @@ libc_bitflags! { SA_NOCLDSTOP; /// When catching a [`Signal::SIGCHLD`] signal, the system will not /// create zombie processes when children of the calling process exit. + #[cfg(not(target_os = "hurd"))] SA_NOCLDWAIT; /// Further occurrences of the delivered signal are not masked during /// the execution of the handler. @@ -486,7 +480,7 @@ use std::iter::IntoIterator; // 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)] +#[derive(Clone, Copy, Debug, Eq)] pub struct SigSet { sigset: libc::sigset_t } @@ -577,7 +571,6 @@ impl SigSet { /// 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; @@ -589,6 +582,35 @@ impl SigSet { }) } + /// Wait for a signal + /// + /// # Return value + /// If `sigsuspend(2)` is interrupted (EINTR), this function returns `Ok`. + /// If `sigsuspend(2)` set other error, this function returns `Err`. + /// + /// For more information see the + /// [`sigsuspend(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsuspend.html). + #[cfg(any( + bsd, + linux_android, + solarish, + target_os = "haiku", + target_os = "hurd", + target_os = "aix", + target_os = "fushsia" + ))] + #[doc(alias("sigsuspend"))] + pub fn suspend(&self) -> Result<()> { + let res = unsafe { + libc::sigsuspend(&self.sigset as *const libc::sigset_t) + }; + match Errno::result(res).map(drop) { + Err(Errno::EINTR) => Ok(()), + Err(e) => Err(e), + Ok(_) => unreachable!("because this syscall always returns -1 if returns"), + } + } + /// Converts a `libc::sigset_t` object to a [`SigSet`] without checking whether the /// `libc::sigset_t` is already initialized. /// @@ -603,6 +625,42 @@ impl SigSet { } } +impl From<Signal> for SigSet { + fn from(signal: Signal) -> SigSet { + let mut sigset = SigSet::empty(); + sigset.add(signal); + sigset + } +} + +impl BitOr for Signal { + type Output = SigSet; + + fn bitor(self, rhs: Self) -> Self::Output { + let mut sigset = SigSet::empty(); + sigset.add(self); + sigset.add(rhs); + sigset + } +} + +impl BitOr<Signal> for SigSet { + type Output = SigSet; + + fn bitor(mut self, rhs: Signal) -> Self::Output { + self.add(rhs); + self + } +} + +impl BitOr for SigSet { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + self.iter().chain(rhs.iter()).collect() + } +} + impl AsRef<libc::sigset_t> for SigSet { fn as_ref(&self) -> &libc::sigset_t { &self.sigset @@ -628,6 +686,27 @@ impl FromIterator<Signal> for SigSet { } } +impl PartialEq for SigSet { + fn eq(&self, other: &Self) -> bool { + for signal in Signal::iterator() { + if self.contains(signal) != other.contains(signal) { + return false; + } + } + true + } +} + +impl Hash for SigSet { + fn hash<H: Hasher>(&self, state: &mut H) { + for signal in Signal::iterator() { + if self.contains(signal) { + signal.hash(state); + } + } + } +} + /// Iterator for a [`SigSet`]. /// /// Call [`SigSet::iter`] to create an iterator. @@ -670,7 +749,6 @@ pub enum SigHandler { /// 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)) } @@ -689,23 +767,27 @@ impl SigAction { pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction { #[cfg(not(target_os = "aix"))] 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, - }; + unsafe { + (*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, + }; + } } #[cfg(target_os = "aix")] unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) { - (*p).sa_union.__su_sigaction = match handler { - SigHandler::SigDfl => mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_DFL), - SigHandler::SigIgn => mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_IGN), - SigHandler::Handler(f) => mem::transmute::<extern "C" fn(i32), extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void)>(f), - SigHandler::SigAction(f) => f, - }; + unsafe { + (*p).sa_union.__su_sigaction = match handler { + SigHandler::SigDfl => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_DFL) }, + SigHandler::SigIgn => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_IGN) }, + SigHandler::Handler(f) => unsafe { mem::transmute::<extern "C" fn(i32), extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void)>(f) }, + SigHandler::SigAction(f) => f, + }; + } } let mut s = mem::MaybeUninit::<libc::sigaction>::uninit(); @@ -810,11 +892,11 @@ impl SigAction { 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, + let res = unsafe { libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, - oldact.as_mut_ptr()); + oldact.as_mut_ptr()) }; - Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() }) + Errno::result(res).map(|_| SigAction { sigaction: unsafe { oldact.assume_init() } }) } /// Signal management (see [signal(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html)) @@ -872,9 +954,9 @@ pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigActi 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), + SigHandler::SigDfl => unsafe { libc::signal(signal, libc::SIG_DFL) }, + SigHandler::SigIgn => unsafe { libc::signal(signal, libc::SIG_IGN) }, + SigHandler::Handler(handler) => unsafe { libc::signal(signal, handler as libc::sighandler_t) }, #[cfg(not(target_os = "redox"))] SigHandler::SigAction(_) => return Err(Errno::ENOTSUP), }; @@ -883,9 +965,7 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> 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)), + unsafe { *(&p as *const usize as *const extern fn(libc::c_int)) } as extern fn(libc::c_int)), } }) } @@ -1019,14 +1099,14 @@ feature! { #[cfg(target_os = "freebsd")] pub type type_of_thread_id = libc::lwpid_t; /// Identifies a thread for [`SigevNotify::SigevThreadId`] -#[cfg(any(target_env = "gnu", target_env = "uclibc"))] +#[cfg(all(not(target_os = "hurd"), any(target_env = "gnu", target_env = "uclibc")))] 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 = "fuchsia", target_os = "openbsd", target_os = "redox")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "hurd", target_os = "openbsd", target_os = "redox")))] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum SigevNotify { /// No notification will be delivered @@ -1041,8 +1121,7 @@ pub enum SigevNotify { }, // Note: SIGEV_THREAD is not implemented, but could be if desired. /// Notify by delivering an event to a kqueue. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(freebsdlike)] SigevKevent { /// File descriptor of the kqueue to notify. kq: RawFd, @@ -1051,7 +1130,6 @@ pub enum SigevNotify { }, /// Notify by delivering an event to a kqueue, with optional event flags set #[cfg(target_os = "freebsd")] - #[cfg_attr(docsrs, doc(cfg(all())))] #[cfg(feature = "event")] SigevKeventFlags { /// File descriptor of the kqueue to notify. @@ -1067,7 +1145,6 @@ pub enum SigevNotify { target_env = "gnu", target_env = "uclibc", ))] - #[cfg_attr(docsrs, doc(cfg(all())))] SigevThreadId { /// Signal to send signal: Signal, @@ -1082,10 +1159,10 @@ pub enum SigevNotify { #[cfg(not(any( target_os = "fuchsia", + target_os = "hurd", target_os = "openbsd", target_os = "redox" )))] -#[cfg_attr(docsrs, doc(cfg(all())))] mod sigevent { feature! { #![any(feature = "aio", feature = "signal")] @@ -1251,7 +1328,7 @@ mod sigevent { sev.sigev_signo = signal as libc::c_int; sev.sigev_value.sival_ptr = si_value as *mut libc::c_void }, - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] + #[cfg(freebsdlike)] SigevNotify::SigevKevent{kq, udata} => { sev.sigev_notify = libc::SIGEV_KEVENT; sev.sigev_signo = kq; @@ -1331,227 +1408,3 @@ mod 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/third_party/rust/nix/src/sys/signalfd.rs b/third_party/rust/nix/src/sys/signalfd.rs index 2b80ea643f..ccba774d1a 100644 --- a/third_party/rust/nix/src/sys/signalfd.rs +++ b/third_party/rust/nix/src/sys/signalfd.rs @@ -21,7 +21,7 @@ use crate::Result; pub use libc::signalfd_siginfo as siginfo; use std::mem; -use std::os::unix::io::{AsRawFd, RawFd, FromRawFd, OwnedFd, AsFd, BorrowedFd}; +use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd}; libc_bitflags! { pub struct SfdFlags: libc::c_int { @@ -45,18 +45,23 @@ pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>(); /// /// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html) #[deprecated(since = "0.27.0", note = "Use SignalFd instead")] -pub fn signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> { +pub fn signalfd<F: AsFd>( + fd: Option<F>, + mask: &SigSet, + flags: SfdFlags, +) -> Result<OwnedFd> { _signalfd(fd, mask, flags) } -fn _signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> { - let raw_fd = fd.map_or(-1, |x|x.as_fd().as_raw_fd()); +fn _signalfd<F: AsFd>( + fd: Option<F>, + mask: &SigSet, + flags: SfdFlags, +) -> Result<OwnedFd> { + let raw_fd = fd.map_or(-1, |x| x.as_fd().as_raw_fd()); unsafe { - Errno::result(libc::signalfd( - raw_fd, - mask.as_ref(), - flags.bits(), - )).map(|raw_fd|FromRawFd::from_raw_fd(raw_fd)) + Errno::result(libc::signalfd(raw_fd, mask.as_ref(), flags.bits())) + .map(|raw_fd| FromRawFd::from_raw_fd(raw_fd)) } } @@ -101,7 +106,7 @@ impl SignalFd { } pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> { - _signalfd(Some(self.0.as_fd()), mask, SfdFlags::empty()).map(drop) + self.update(mask, SfdFlags::empty()) } pub fn read_signal(&mut self) -> Result<Option<siginfo>> { @@ -109,7 +114,7 @@ impl SignalFd { let size = mem::size_of_val(&buffer); let res = Errno::result(unsafe { - libc::read(self.0.as_raw_fd(), buffer.as_mut_ptr() as *mut libc::c_void, size) + libc::read(self.0.as_raw_fd(), buffer.as_mut_ptr().cast(), size) }) .map(|r| r as usize); match res { @@ -119,6 +124,14 @@ impl SignalFd { Err(error) => Err(error), } } + + fn update(&self, mask: &SigSet, flags: SfdFlags) -> Result<()> { + let raw_fd = self.0.as_raw_fd(); + unsafe { + Errno::result(libc::signalfd(raw_fd, mask.as_ref(), flags.bits())) + .map(drop) + } + } } impl AsFd for SignalFd { @@ -142,34 +155,3 @@ impl Iterator for SignalFd { } } } - -#[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/third_party/rust/nix/src/sys/socket/addr.rs b/third_party/rust/nix/src/sys/socket/addr.rs index 1783531d49..f6800aa5d0 100644 --- a/third_party/rust/nix/src/sys/socket/addr.rs +++ b/third_party/rust/nix/src/sys/socket/addr.rs @@ -1,31 +1,22 @@ #[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", + bsd, + linux_android, + solarish, target_os = "haiku", target_os = "fuchsia", target_os = "aix", ))] #[cfg(feature = "net")] pub use self::datalink::LinkAddr; -#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] +#[cfg(any(linux_android, apple_targets))] pub use self::vsock::VsockAddr; use super::sa_family_t; use crate::errno::Errno; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] use crate::sys::socket::addr::alg::AlgAddr; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] use crate::sys::socket::addr::netlink::NetlinkAddr; -#[cfg(all( - feature = "ioctl", - any(target_os = "ios", target_os = "macos") -))] +#[cfg(all(feature = "ioctl", apple_targets))] use crate::sys::socket::addr::sys_control::SysControlAddr; use crate::{NixPath, Result}; use cfg_if::cfg_if; @@ -33,6 +24,7 @@ use memoffset::offset_of; use std::convert::TryInto; use std::ffi::OsStr; use std::hash::{Hash, Hasher}; +use std::net::{Ipv4Addr, Ipv6Addr}; use std::os::unix::ffi::OsStrExt; use std::path::Path; use std::{fmt, mem, net, ptr, slice}; @@ -41,7 +33,7 @@ use std::{fmt, mem, net, ptr, slice}; #[cfg(feature = "net")] pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr { libc::in_addr { - s_addr: u32::from_ne_bytes(addr.octets()) + s_addr: u32::from_ne_bytes(addr.octets()), } } @@ -49,7 +41,7 @@ pub(crate) const fn ipv4addr_to_libc(addr: net::Ipv4Addr) -> libc::in_addr { #[cfg(feature = "net")] pub(crate) const fn ipv6addr_to_libc(addr: &net::Ipv6Addr) -> libc::in6_addr { libc::in6_addr { - s6_addr: addr.octets() + s6_addr: addr.octets(), } } @@ -71,346 +63,188 @@ pub enum AddressFamily { /// 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())))] + #[cfg(linux_android)] Netlink = libc::AF_NETLINK, /// Kernel interface for interacting with the routing table - #[cfg(not(any( - target_os = "redox", - target_os = "linux", - target_os = "android" - )))] + #[cfg(not(any(linux_android, target_os = "redox")))] Route = libc::PF_ROUTE, /// 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())))] + #[cfg(any(linux_android, solarish, target_os = "fuchsia"))] Packet = libc::AF_PACKET, /// KEXT Controls and Notifications - #[cfg(any(target_os = "ios", target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(apple_targets)] System = libc::AF_SYSTEM, /// Amateur radio AX.25 protocol - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] Ax25 = libc::AF_AX25, /// IPX - Novell protocols #[cfg(not(any(target_os = "aix", target_os = "redox")))] - #[cfg_attr(docsrs, doc(cfg(all())))] Ipx = libc::AF_IPX, /// AppleTalk #[cfg(not(target_os = "redox"))] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] Bridge = libc::AF_BRIDGE, /// Access to raw ATM PVCs - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] Rose = libc::AF_ROSE, /// DECet protocol sockets. #[cfg(not(any(target_os = "haiku", target_os = "redox")))] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] Security = libc::AF_SECURITY, /// Key management protocol. - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] Ash = libc::AF_ASH, /// Acorn Econet protocol - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] Econet = libc::AF_ECONET, /// Access to ATM Switched Virtual Circuits - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] AtmSvc = libc::AF_ATMSVC, /// Reliable Datagram Sockets (RDS) protocol - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] Rds = libc::AF_RDS, /// IBM SNA #[cfg(not(any(target_os = "haiku", target_os = "redox")))] Sna = libc::AF_SNA, /// Socket interface over IrDA - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] Can = libc::AF_CAN, /// TIPC, "cluster domain sockets" protocol - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] Tipc = libc::AF_TIPC, /// Bluetooth low-level socket protocol #[cfg(not(any( target_os = "aix", - target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "solaris", + solarish, + apple_targets, + target_os = "hurd", target_os = "redox", )))] - #[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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] RxRpc = libc::AF_RXRPC, /// New "modular ISDN" driver interface protocol #[cfg(not(any( target_os = "aix", - target_os = "illumos", - target_os = "solaris", + solarish, target_os = "haiku", + target_os = "hurd", target_os = "redox", )))] - #[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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] Caif = libc::AF_CAIF, /// Interface to kernel crypto API - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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", target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(any(linux_android, apple_targets))] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(any(apple_targets, netbsdlike))] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(any(bsd, solarish))] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(linux_android)] Unspec = libc::AF_UNSPEC, } @@ -425,29 +259,17 @@ impl AddressFamily { 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"))] + #[cfg(linux_android)] libc::AF_NETLINK => Some(AddressFamily::Netlink), - #[cfg(any(target_os = "macos", target_os = "macos"))] + #[cfg(apple_targets)] libc::AF_SYSTEM => Some(AddressFamily::System), - #[cfg(not(any( - target_os = "redox", - target_os = "linux", - target_os = "android" - )))] + #[cfg(not(any(linux_android, target_os = "redox")))] libc::PF_ROUTE => Some(AddressFamily::Route), - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] 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" - ))] + #[cfg(any(bsd, solarish))] libc::AF_LINK => Some(AddressFamily::Link), - #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] + #[cfg(any(linux_android, apple_targets))] libc::AF_VSOCK => Some(AddressFamily::Vsock), _ => None, } @@ -463,13 +285,7 @@ pub struct UnixAddr { /// 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", - target_os = "redox", - ))] + #[cfg(not(any(bsd, target_os = "haiku", target_os = "hurd")))] sun_len: u8, } @@ -483,12 +299,12 @@ pub struct UnixAddr { enum UnixAddrKind<'a> { Pathname(&'a Path), Unnamed, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] Abstract(&'a [u8]), } impl<'a> UnixAddrKind<'a> { /// Safety: sun & sun_len must be valid - #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms + #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms 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 = @@ -496,16 +312,19 @@ impl<'a> UnixAddrKind<'a> { if path_len == 0 { return Self::Unnamed; } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] 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, - ); + let name = unsafe { + slice::from_raw_parts( + sun.sun_path.as_ptr().add(1).cast(), + path_len - 1, + ) + }; return Self::Abstract(name); } - let pathname = - slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len); + let pathname = unsafe { + slice::from_raw_parts(sun.sun_path.as_ptr().cast(), 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 @@ -525,7 +344,7 @@ impl<'a> UnixAddrKind<'a> { impl UnixAddr { /// Create a new sockaddr_un representing a filesystem path. - #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms + #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> { path.with_nix_path(|cstr| unsafe { let mut ret = libc::sockaddr_un { @@ -544,20 +363,13 @@ impl UnixAddr { .try_into() .unwrap(); - #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" - ))] + #[cfg(any(bsd, target_os = "haiku", target_os = "hurd"))] { ret.sun_len = sun_len; } ptr::copy_nonoverlapping( bytes.as_ptr(), - ret.sun_path.as_mut_ptr() as *mut u8, + ret.sun_path.as_mut_ptr().cast(), bytes.len(), ); @@ -571,9 +383,8 @@ impl UnixAddr { /// 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())))] - #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms + #[cfg(linux_android)] + #[allow(clippy::unnecessary_cast)] // Not unnecessary on all platforms pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> { unsafe { let mut ret = libc::sockaddr_un { @@ -593,7 +404,7 @@ impl UnixAddr { // 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, + ret.sun_path.as_mut_ptr().offset(1).cast(), path.len(), ); @@ -602,8 +413,7 @@ impl UnixAddr { } /// 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())))] + #[cfg(linux_android)] pub fn new_unnamed() -> UnixAddr { let ret = libc::sockaddr_un { sun_family: AddressFamily::Unix as sa_family_t, @@ -632,10 +442,9 @@ impl UnixAddr { sun_len: u8, ) -> UnixAddr { cfg_if! { - if #[cfg(any(target_os = "android", + if #[cfg(any(linux_android, target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", + solarish, target_os = "redox", ))] { @@ -664,8 +473,7 @@ impl UnixAddr { /// /// 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())))] + #[cfg(linux_android)] pub fn as_abstract(&self) -> Option<&[u8]> { match self.kind() { UnixAddrKind::Abstract(name) => Some(name), @@ -674,8 +482,7 @@ impl UnixAddr { } /// Check if this address is an "unnamed" unix socket address. - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] #[inline] pub fn is_unnamed(&self) -> bool { matches!(self.kind(), UnixAddrKind::Unnamed) @@ -699,10 +506,9 @@ impl UnixAddr { fn sun_len(&self) -> u8 { cfg_if! { - if #[cfg(any(target_os = "android", + if #[cfg(any(linux_android, target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", + solarish, target_os = "redox", ))] { @@ -717,10 +523,10 @@ impl UnixAddr { impl private::SockaddrLikePriv for UnixAddr {} impl SockaddrLike for UnixAddr { #[cfg(any( - target_os = "android", + linux_android, target_os = "fuchsia", - target_os = "illumos", - target_os = "linux" + solarish, + target_os = "redox" ))] fn len(&self) -> libc::socklen_t { self.sun_len.into() @@ -740,27 +546,26 @@ impl SockaddrLike for UnixAddr { return None; } } - if (*addr).sa_family as i32 != libc::AF_UNIX { + if unsafe { (*addr).sa_family as i32 != libc::AF_UNIX } { return None; } - let mut su: libc::sockaddr_un = mem::zeroed(); + let mut su: libc::sockaddr_un = unsafe { mem::zeroed() }; let sup = &mut su as *mut libc::sockaddr_un as *mut u8; cfg_if! { - if #[cfg(any(target_os = "android", + if #[cfg(any(linux_android, target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", + solarish, target_os = "redox", ))] { 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); + let su_len = unsafe { 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)) + } + unsafe { ptr::copy(addr as *const u8, sup, su_len as usize) }; + Some(unsafe { Self::from_raw_parts(su, su_len as u8) }) } fn size() -> libc::socklen_t @@ -770,14 +575,16 @@ impl SockaddrLike for UnixAddr { mem::size_of::<libc::sockaddr_un>() as libc::socklen_t } - unsafe fn set_length(&mut self, new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> { + unsafe fn set_length( + &mut self, + new_length: usize, + ) -> std::result::Result<(), SocketAddressLengthNotDynamic> { // `new_length` is only used on some platforms, so it must be provided even when not used #![allow(unused_variables)] cfg_if! { - if #[cfg(any(target_os = "android", + if #[cfg(any(linux_android, target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", + solarish, target_os = "redox", ))] { self.sun_len = new_length as u8; @@ -793,7 +600,7 @@ impl AsRef<libc::sockaddr_un> for UnixAddr { } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result { use fmt::Write; f.write_str("@\"")?; @@ -810,7 +617,7 @@ impl fmt::Display for UnixAddr { 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"))] + #[cfg(linux_android)] UnixAddrKind::Abstract(name) => fmt_abstract(name, f), } } @@ -894,12 +701,7 @@ pub trait SockaddrLike: private::SockaddrLikePriv { } cfg_if! { - if #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] { + if #[cfg(bsd)] { /// Return the length of valid data in the sockaddr structure. /// /// For fixed-size sockaddrs, this should be the size of the @@ -946,7 +748,10 @@ pub trait SockaddrLike: private::SockaddrLikePriv { /// `new_length` must be a valid length for this type of address. Specifically, reads of that /// length from `self` must be valid. #[doc(hidden)] - unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> { + unsafe fn set_length( + &mut self, + _new_length: usize, + ) -> std::result::Result<(), SocketAddressLengthNotDynamic> { Err(SocketAddressLengthNotDynamic) } } @@ -1006,22 +811,20 @@ pub struct SockaddrIn(libc::sockaddr_in); 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) + pub const fn ip(&self) -> net::Ipv4Addr { + let bytes = self.0.sin_addr.s_addr.to_ne_bytes(); + let (a, b, c, d) = (bytes[0], bytes[1], bytes[2], bytes[3]); + Ipv4Addr::new(a, b, c, d) } /// 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", + bsd, target_os = "aix", target_os = "haiku", - target_os = "openbsd" + target_os = "hurd" ))] sin_len: Self::size() as u8, sin_family: AddressFamily::Inet as sa_family_t, @@ -1056,10 +859,10 @@ impl SockaddrLike for SockaddrIn { return None; } } - if (*addr).sa_family as i32 != libc::AF_INET { + if unsafe { (*addr).sa_family as i32 != libc::AF_INET } { return None; } - Some(Self(ptr::read_unaligned(addr as *const _))) + Some(Self(unsafe { ptr::read_unaligned(addr as *const _) })) } } @@ -1092,14 +895,10 @@ impl From<net::SocketAddrV4> for SockaddrIn { fn from(addr: net::SocketAddrV4) -> Self { Self(libc::sockaddr_in { #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", + bsd, target_os = "haiku", target_os = "hermit", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" + target_os = "hurd" ))] sin_len: mem::size_of::<libc::sockaddr_in>() as u8, sin_family: AddressFamily::Inet as sa_family_t, @@ -1143,8 +942,19 @@ impl SockaddrIn6 { } /// Returns the IP address associated with this socket address. - pub fn ip(&self) -> net::Ipv6Addr { - net::Ipv6Addr::from(self.0.sin6_addr.s6_addr) + pub const fn ip(&self) -> net::Ipv6Addr { + let bytes = self.0.sin6_addr.s6_addr; + let (a, b, c, d, e, f, g, h) = ( + ((bytes[0] as u16) << 8) | bytes[1] as u16, + ((bytes[2] as u16) << 8) | bytes[3] as u16, + ((bytes[4] as u16) << 8) | bytes[5] as u16, + ((bytes[6] as u16) << 8) | bytes[7] as u16, + ((bytes[8] as u16) << 8) | bytes[9] as u16, + ((bytes[10] as u16) << 8) | bytes[11] as u16, + ((bytes[12] as u16) << 8) | bytes[13] as u16, + ((bytes[14] as u16) << 8) | bytes[15] as u16, + ); + Ipv6Addr::new(a, b, c, d, e, f, g, h) } /// Returns the port number associated with this socket address, in native @@ -1175,10 +985,10 @@ impl SockaddrLike for SockaddrIn6 { return None; } } - if (*addr).sa_family as i32 != libc::AF_INET6 { + if unsafe { (*addr).sa_family as i32 != libc::AF_INET6 } { return None; } - Some(Self(ptr::read_unaligned(addr as *const _))) + Some(Self(unsafe { ptr::read_unaligned(addr as *const _) })) } } @@ -1210,14 +1020,10 @@ impl From<net::SocketAddrV6> for SockaddrIn6 { #[allow(clippy::needless_update)] // It isn't needless on Illumos Self(libc::sockaddr_in6 { #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", + bsd, target_os = "haiku", target_os = "hermit", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" + target_os = "hurd" ))] sin6_len: mem::size_of::<libc::sockaddr_in6>() as u8, sin6_family: AddressFamily::Inet6 as sa_family_t, @@ -1273,18 +1079,17 @@ impl std::str::FromStr for SockaddrIn6 { #[derive(Clone, Copy, Eq)] #[repr(C)] pub union SockaddrStorage { - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] alg: AlgAddr, - #[cfg(all(feature = "net", not(target_os = "redox")))] + #[cfg(all( + feature = "net", + not(any(target_os = "hurd", target_os = "redox")) + ))] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] dl: LinkAddr, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] nl: NetlinkAddr, - #[cfg(all( - feature = "ioctl", - any(target_os = "ios", target_os = "macos") - ))] + #[cfg(all(feature = "ioctl", apple_targets))] #[cfg_attr(docsrs, doc(cfg(feature = "ioctl")))] sctl: SysControlAddr, #[cfg(feature = "net")] @@ -1293,8 +1098,7 @@ pub union SockaddrStorage { sin6: SockaddrIn6, ss: libc::sockaddr_storage, su: UnixAddr, - #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos" ))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(any(linux_android, apple_targets))] vsock: VsockAddr, } impl private::SockaddrLikePriv for SockaddrStorage {} @@ -1316,21 +1120,22 @@ impl SockaddrLike for SockaddrStorage { { None } else { - let mut ss: libc::sockaddr_storage = mem::zeroed(); + let mut ss: libc::sockaddr_storage = unsafe { mem::zeroed() }; let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8; - ptr::copy(addr as *const u8, ssp, len as usize); + unsafe { ptr::copy(addr as *const u8, ssp, len as usize) }; #[cfg(any( - target_os = "android", + linux_android, target_os = "fuchsia", - target_os = "illumos", - target_os = "linux" + solarish, ))] 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; + unsafe { + (*(&mut ss as *mut libc::sockaddr_storage + as *mut UnixAddr)) + .sun_len = len as u8; + } } Some(Self { ss }) } @@ -1338,68 +1143,47 @@ impl SockaddrLike for SockaddrStorage { // 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 => { + match unsafe { (*addr).sa_family as i32 } { + #[cfg(linux_android)] + libc::AF_ALG => unsafe { AlgAddr::from_raw(addr, l).map(|alg| Self { alg }) - } + }, #[cfg(feature = "net")] - libc::AF_INET => { + libc::AF_INET => unsafe { SockaddrIn::from_raw(addr, l).map(|sin| Self { sin }) - } + }, #[cfg(feature = "net")] - libc::AF_INET6 => { + libc::AF_INET6 => unsafe { 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(any(bsd, solarish, target_os = "haiku"))] #[cfg(feature = "net")] - libc::AF_LINK => { + libc::AF_LINK => unsafe { LinkAddr::from_raw(addr, l).map(|dl| Self { dl }) - } - #[cfg(any(target_os = "android", target_os = "linux"))] - libc::AF_NETLINK => { + }, + #[cfg(linux_android)] + libc::AF_NETLINK => unsafe { NetlinkAddr::from_raw(addr, l).map(|nl| Self { nl }) - } - #[cfg(any( - target_os = "android", - target_os = "fuchsia", - target_os = "linux" - ))] + }, + #[cfg(any(linux_android, target_os = "fuchsia"))] #[cfg(feature = "net")] - libc::AF_PACKET => { + libc::AF_PACKET => unsafe { LinkAddr::from_raw(addr, l).map(|dl| Self { dl }) - } - #[cfg(all( - feature = "ioctl", - any(target_os = "ios", target_os = "macos") - ))] - libc::AF_SYSTEM => { + }, + #[cfg(all(feature = "ioctl", apple_targets))] + libc::AF_SYSTEM => unsafe { SysControlAddr::from_raw(addr, l).map(|sctl| Self { sctl }) - } - #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos" ))] - libc::AF_VSOCK => { + }, + #[cfg(any(linux_android, apple_targets))] + libc::AF_VSOCK => unsafe { VsockAddr::from_raw(addr, l).map(|vsock| Self { vsock }) - } + }, _ => None, } } } - #[cfg(any( - target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux" - ))] + #[cfg(any(linux_android, target_os = "fuchsia", solarish))] fn len(&self) -> libc::socklen_t { match self.as_unix_addr() { // The UnixAddr type knows its own length @@ -1409,11 +1193,12 @@ impl SockaddrLike for SockaddrStorage { } } - unsafe fn set_length(&mut self, new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> { + unsafe fn set_length( + &mut self, + new_length: usize, + ) -> std::result::Result<(), SocketAddressLengthNotDynamic> { match self.as_unix_addr_mut() { - Some(addr) => { - addr.set_length(new_length) - }, + Some(addr) => unsafe { addr.set_length(new_length) }, None => Err(SocketAddressLengthNotDynamic), } } @@ -1457,10 +1242,9 @@ impl SockaddrStorage { /// Downcast to an immutable `[UnixAddr]` reference. pub fn as_unix_addr(&self) -> Option<&UnixAddr> { cfg_if! { - if #[cfg(any(target_os = "android", + if #[cfg(any(linux_android, target_os = "fuchsia", - target_os = "illumos", - target_os = "linux" + solarish, ))] { let p = unsafe{ &self.ss as *const libc::sockaddr_storage }; @@ -1487,10 +1271,9 @@ impl SockaddrStorage { /// 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", + if #[cfg(any(linux_android, target_os = "fuchsia", - target_os = "illumos", - target_os = "linux" + solarish, ))] { let p = unsafe{ &self.ss as *const libc::sockaddr_storage }; @@ -1514,29 +1297,17 @@ impl SockaddrStorage { } } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] 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(any(linux_android, target_os = "fuchsia"))] #[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(any(bsd, solarish))] #[cfg(feature = "net")] accessors! { as_link_addr, as_link_addr_mut, LinkAddr, @@ -1552,17 +1323,16 @@ impl SockaddrStorage { as_sockaddr_in6, as_sockaddr_in6_mut, SockaddrIn6, AddressFamily::Inet6, libc::sockaddr_in6, sin6} - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] 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(all(feature = "ioctl", apple_targets))] #[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", target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(any(linux_android, apple_targets))] accessors! {as_vsock_addr, as_vsock_addr_mut, VsockAddr, AddressFamily::Vsock, libc::sockaddr_vm, vsock} } @@ -1581,37 +1351,25 @@ 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"))] + #[cfg(linux_android)] 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(any(bsd, solarish))] #[cfg(feature = "net")] libc::AF_LINK => self.dl.fmt(f), - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] libc::AF_NETLINK => self.nl.fmt(f), - #[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "fuchsia" - ))] + #[cfg(any(linux_android, target_os = "fuchsia"))] #[cfg(feature = "net")] libc::AF_PACKET => self.dl.fmt(f), - #[cfg(any(target_os = "ios", target_os = "macos"))] + #[cfg(apple_targets)] #[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", target_os = "macos"))] + #[cfg(any(linux_android, apple_targets))] libc::AF_VSOCK => self.vsock.fmt(f), _ => "<Address family unspecified>".fmt(f), } @@ -1655,37 +1413,25 @@ 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"))] + #[cfg(linux_android)] 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(any(bsd, solarish))] #[cfg(feature = "net")] libc::AF_LINK => self.dl.hash(s), - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] libc::AF_NETLINK => self.nl.hash(s), - #[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "fuchsia" - ))] + #[cfg(any(linux_android, target_os = "fuchsia"))] #[cfg(feature = "net")] libc::AF_PACKET => self.dl.hash(s), - #[cfg(any(target_os = "ios", target_os = "macos"))] + #[cfg(apple_targets)] #[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", target_os = "macos"))] + #[cfg(any(linux_android, apple_targets))] libc::AF_VSOCK => self.vsock.hash(s), _ => self.ss.hash(s), } @@ -1697,37 +1443,25 @@ 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"))] + #[cfg(linux_android)] (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(any(bsd, solarish))] #[cfg(feature = "net")] (libc::AF_LINK, libc::AF_LINK) => self.dl == other.dl, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] (libc::AF_NETLINK, libc::AF_NETLINK) => self.nl == other.nl, - #[cfg(any( - target_os = "android", - target_os = "fuchsia", - target_os = "linux" - ))] + #[cfg(any(linux_android, target_os = "fuchsia"))] #[cfg(feature = "net")] (libc::AF_PACKET, libc::AF_PACKET) => self.dl == other.dl, - #[cfg(any(target_os = "ios", target_os = "macos"))] + #[cfg(apple_targets)] #[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", target_os = "macos"))] + #[cfg(any(linux_android, apple_targets))] (libc::AF_VSOCK, libc::AF_VSOCK) => self.vsock == other.vsock, _ => false, } @@ -1751,8 +1485,7 @@ pub(super) mod private { } } -#[cfg(any(target_os = "android", target_os = "linux"))] -#[cfg_attr(docsrs, doc(cfg(all())))] +#[cfg(linux_android)] pub mod netlink { use super::*; use crate::sys::socket::addr::AddressFamily; @@ -1805,10 +1538,10 @@ pub mod netlink { return None; } } - if (*addr).sa_family as i32 != libc::AF_NETLINK { + if unsafe { (*addr).sa_family as i32 != libc::AF_NETLINK } { return None; } - Some(Self(ptr::read_unaligned(addr as *const _))) + Some(Self(unsafe { ptr::read_unaligned(addr as *const _) })) } } @@ -1825,11 +1558,10 @@ pub mod netlink { } } -#[cfg(any(target_os = "android", target_os = "linux"))] -#[cfg_attr(docsrs, doc(cfg(all())))] +#[cfg(linux_android)] pub mod alg { use super::*; - use libc::{c_char, sockaddr_alg, AF_ALG}; + use libc::{sockaddr_alg, AF_ALG}; use std::ffi::CStr; use std::hash::{Hash, Hasher}; use std::{fmt, mem, str}; @@ -1854,10 +1586,10 @@ pub mod alg { return None; } } - if (*addr).sa_family as i32 != libc::AF_ALG { + if unsafe { (*addr).sa_family as i32 != libc::AF_ALG } { return None; } - Some(Self(ptr::read_unaligned(addr as *const _))) + Some(Self(unsafe { ptr::read_unaligned(addr as *const _) })) } } @@ -1918,16 +1650,12 @@ pub mod alg { /// 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) - } + unsafe { CStr::from_ptr(self.0.salg_type.as_ptr().cast()) } } /// 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) - } + unsafe { CStr::from_ptr(self.0.salg_name.as_ptr().cast()) } } } @@ -1951,7 +1679,7 @@ pub mod alg { feature! { #![feature = "ioctl"] -#[cfg(any(target_os = "ios", target_os = "macos"))] +#[cfg(apple_targets)] pub mod sys_control { use crate::sys::socket::addr::AddressFamily; use libc::{self, c_uchar}; @@ -1994,10 +1722,10 @@ pub mod sys_control { return None; } } - if (*addr).sa_family as i32 != libc::AF_SYSTEM { + if unsafe { (*addr).sa_family as i32 != libc::AF_SYSTEM } { return None; } - Some(Self(ptr::read_unaligned(addr as *const _))) + Some(Self(unsafe { ptr::read_unaligned(addr as *const _) } )) } } @@ -2058,8 +1786,7 @@ pub mod sys_control { } } -#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))] -#[cfg_attr(docsrs, doc(cfg(all())))] +#[cfg(any(linux_android, target_os = "fuchsia"))] mod datalink { feature! { #![feature = "net"] @@ -2136,10 +1863,10 @@ mod datalink { return None; } } - if (*addr).sa_family as i32 != libc::AF_PACKET { + if unsafe { (*addr).sa_family as i32 != libc::AF_PACKET } { return None; } - Some(Self(ptr::read_unaligned(addr as *const _))) + Some(Self(unsafe { ptr::read_unaligned(addr as *const _) })) } } @@ -2152,18 +1879,7 @@ mod datalink { } } -#[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 = "aix", - target_os = "openbsd" -))] -#[cfg_attr(docsrs, doc(cfg(all())))] +#[cfg(any(bsd, solarish, target_os = "haiku", target_os = "aix"))] mod datalink { feature! { #![feature = "net"] @@ -2261,10 +1977,10 @@ mod datalink { return None; } } - if (*addr).sa_family as i32 != libc::AF_LINK { + if unsafe { (*addr).sa_family as i32 != libc::AF_LINK } { return None; } - Some(Self(ptr::read_unaligned(addr as *const _))) + Some(Self(unsafe { ptr::read_unaligned(addr as *const _) })) } } @@ -2276,8 +1992,7 @@ mod datalink { } } -#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] -#[cfg_attr(docsrs, doc(cfg(all())))] +#[cfg(any(linux_android, apple_targets))] pub mod vsock { use super::*; use crate::sys::socket::addr::AddressFamily; @@ -2308,10 +2023,10 @@ pub mod vsock { return None; } } - if (*addr).sa_family as i32 != libc::AF_VSOCK { + if unsafe { (*addr).sa_family as i32 != libc::AF_VSOCK } { return None; } - Some(Self(ptr::read_unaligned(addr as *const _))) + unsafe { Some(Self(ptr::read_unaligned(addr as *const _))) } } } @@ -2322,32 +2037,47 @@ pub mod vsock { } impl PartialEq for VsockAddr { - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] 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) } - #[cfg(target_os = "macos")] + #[cfg(apple_targets)] fn eq(&self, other: &Self) -> bool { let (inner, other) = (self.0, other.0); - (inner.svm_family, inner.svm_cid, inner.svm_port, inner.svm_len) - == (other.svm_family, other.svm_cid, other.svm_port, inner.svm_len) + ( + inner.svm_family, + inner.svm_cid, + inner.svm_port, + inner.svm_len, + ) == ( + other.svm_family, + other.svm_cid, + other.svm_port, + inner.svm_len, + ) } } impl Eq for VsockAddr {} impl Hash for VsockAddr { - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] fn hash<H: Hasher>(&self, s: &mut H) { let inner = self.0; (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s); } - #[cfg(target_os = "macos")] + #[cfg(apple_targets)] fn hash<H: Hasher>(&self, s: &mut H) { let inner = self.0; - (inner.svm_family, inner.svm_cid, inner.svm_port, inner.svm_len).hash(s); + ( + inner.svm_family, + inner.svm_cid, + inner.svm_port, + inner.svm_len, + ) + .hash(s); } } @@ -2363,9 +2093,9 @@ pub mod vsock { addr.svm_cid = cid; addr.svm_port = port; - #[cfg(target_os = "macos")] + #[cfg(apple_targets)] { - addr.svm_len = std::mem::size_of::<sockaddr_vm>() as u8; + addr.svm_len = std::mem::size_of::<sockaddr_vm>() as u8; } VsockAddr(addr) } @@ -2419,27 +2149,16 @@ mod tests { } } - #[cfg(not(target_os = "redox"))] + #[cfg(not(any(target_os = "hurd", target_os = "redox")))] mod link { #![allow(clippy::cast_ptr_alignment)] - #[cfg(any( - target_os = "ios", - target_os = "macos", - target_os = "illumos" - ))] + #[cfg(any(apple_targets, solarish))] 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" - ))] + #[cfg(bsd)] #[test] fn test_datalink_display() { use super::super::LinkAddr; @@ -2459,11 +2178,7 @@ mod tests { } #[cfg(all( - any( - target_os = "android", - target_os = "fuchsia", - target_os = "linux" - ), + any(linux_android, target_os = "fuchsia"), target_endian = "little" ))] #[test] @@ -2474,7 +2189,7 @@ mod tests { 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 sa = bytes.0.as_ptr().cast(); let len = None; let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap(); @@ -2485,12 +2200,12 @@ mod tests { } } - #[cfg(any(target_os = "ios", target_os = "macos"))] + #[cfg(apple_targets)] #[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 sa = bytes.as_ptr().cast(); let len = Some(bytes.len() as socklen_t); let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap(); @@ -2503,7 +2218,7 @@ mod tests { } } - #[cfg(any(target_os = "ios", target_os = "macos"))] + #[cfg(apple_targets)] #[test] fn macos_tap() { let bytes = [ @@ -2525,9 +2240,9 @@ mod tests { } } - #[cfg(target_os = "illumos")] + #[cfg(solarish)] #[test] - fn illumos_tap() { + fn solarish_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; @@ -2548,23 +2263,9 @@ mod tests { #[test] fn size() { - #[cfg(any( - target_os = "aix", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "openbsd", - target_os = "haiku" - ))] + #[cfg(any(bsd, target_os = "aix", solarish, target_os = "haiku"))] let l = mem::size_of::<libc::sockaddr_dl>(); - #[cfg(any( - target_os = "android", - target_os = "fuchsia", - target_os = "linux" - ))] + #[cfg(any(linux_android, target_os = "fuchsia"))] let l = mem::size_of::<libc::sockaddr_ll>(); assert_eq!(LinkAddr::size() as usize, l); } @@ -2588,6 +2289,13 @@ mod tests { SockaddrIn::size() as usize ); } + + #[test] + fn ip() { + let s = "127.0.0.1:8082"; + let ip = SockaddrIn::from_str(s).unwrap().ip(); + assert_eq!("127.0.0.1", format!("{ip}")); + } } mod sockaddr_in6 { @@ -2610,6 +2318,13 @@ mod tests { } #[test] + fn ip() { + let s = "[1234:5678:90ab:cdef::1111:2222]:8080"; + let ip = SockaddrIn6::from_str(s).unwrap().ip(); + assert_eq!("1234:5678:90ab:cdef::1111:2222", format!("{ip}")); + } + + #[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"; @@ -2628,28 +2343,28 @@ mod tests { #[test] fn from_sockaddr_un_named() { let ua = UnixAddr::new("/var/run/mysock").unwrap(); - let ptr = ua.as_ptr() as *const libc::sockaddr; + let ptr = ua.as_ptr().cast(); 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"))] + #[cfg(linux_android)] #[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 ptr = ua.as_ptr().cast(); 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"))] + #[cfg(linux_android)] #[test] fn from_sockaddr_un_abstract_unnamed() { let ua = UnixAddr::new_unnamed(); - let ptr = ua.as_ptr() as *const libc::sockaddr; + let ptr = ua.as_ptr().cast(); let ss = unsafe { SockaddrStorage::from_raw(ptr, Some(ua.len())) } .unwrap(); assert_eq!(ss.len(), ua.len()); @@ -2659,7 +2374,7 @@ mod tests { mod unixaddr { use super::*; - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] #[test] fn abstract_sun_path() { let name = String::from("nix\0abstract\0test"); diff --git a/third_party/rust/nix/src/sys/socket/mod.rs b/third_party/rust/nix/src/sys/socket/mod.rs index 78dd617c55..3d1651bd3f 100644 --- a/third_party/rust/nix/src/sys/socket/mod.rs +++ b/third_party/rust/nix/src/sys/socket/mod.rs @@ -1,7 +1,7 @@ //! Socket interface functions //! //! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html) -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(any(target_os = "freebsd", linux_android))] #[cfg(feature = "uio")] use crate::sys::time::TimeSpec; #[cfg(not(target_os = "redox"))] @@ -9,16 +9,16 @@ use crate::sys::time::TimeSpec; use crate::sys::time::TimeVal; use crate::{errno::Errno, Result}; use cfg_if::cfg_if; -use libc::{self, c_int, c_void, size_t, socklen_t}; +use libc::{self, c_int, size_t, socklen_t}; #[cfg(all(feature = "uio", not(target_os = "redox")))] use libc::{ - iovec, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE, + c_void, iovec, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE, }; #[cfg(not(target_os = "redox"))] use std::io::{IoSlice, IoSliceMut}; #[cfg(feature = "net")] use std::net; -use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, RawFd, OwnedFd}; +use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd, RawFd}; use std::{mem, ptr}; #[deny(missing_docs)] @@ -34,35 +34,25 @@ pub mod sockopt; pub use self::addr::{SockaddrLike, SockaddrStorage}; -#[cfg(any(target_os = "illumos", target_os = "solaris"))] +#[cfg(solarish)] pub use self::addr::{AddressFamily, UnixAddr}; -#[cfg(not(any(target_os = "illumos", target_os = "solaris")))] +#[cfg(not(solarish))] pub use self::addr::{AddressFamily, UnixAddr}; -#[cfg(not(any( - target_os = "illumos", - target_os = "solaris", - target_os = "haiku", - target_os = "redox", -)))] +#[cfg(not(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox")))] #[cfg(feature = "net")] pub use self::addr::{LinkAddr, SockaddrIn, SockaddrIn6}; -#[cfg(any( - target_os = "illumos", - target_os = "solaris", - target_os = "haiku", - target_os = "redox", -))] +#[cfg(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox"))] #[cfg(feature = "net")] pub use self::addr::{SockaddrIn, SockaddrIn6}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] pub use crate::sys::socket::addr::alg::AlgAddr; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] pub use crate::sys::socket::addr::netlink::NetlinkAddr; -#[cfg(any(target_os = "ios", target_os = "macos"))] +#[cfg(apple_targets)] #[cfg(feature = "ioctl")] pub use crate::sys::socket::addr::sys_control::SysControlAddr; -#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] +#[cfg(any(linux_android, apple_targets))] pub use crate::sys::socket::addr::vsock::VsockAddr; #[cfg(all(feature = "uio", not(target_os = "redox")))] @@ -132,121 +122,108 @@ pub enum SockProtocol { 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())))] + #[cfg(apple_targets)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] NetlinkSockDiag = libc::NETLINK_SOCK_DIAG, /// Netfilter/iptables ULOG. /// ([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())))] + #[cfg(linux_android)] NetlinkNFLOG = libc::NETLINK_NFLOG, /// 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT, /// Generic netlink family for simplified netlink usage. /// ([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())))] + #[cfg(linux_android)] NetlinkGeneric = libc::NETLINK_GENERIC, /// 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] EthAll = (libc::ETH_P_ALL as u16).to_be() as i32, + /// ICMP protocol ([icmp(7)](https://man7.org/linux/man-pages/man7/icmp.7.html)) + Icmp = libc::IPPROTO_ICMP, + /// ICMPv6 protocol (ICMP over IPv6) + IcmpV6 = libc::IPPROTO_ICMPV6, +} + +impl SockProtocol { /// The Controller Area Network raw socket protocol /// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan)) #[cfg(target_os = "linux")] - #[cfg_attr(docsrs, doc(cfg(all())))] - CanRaw = libc::CAN_RAW, -} + #[allow(non_upper_case_globals)] + pub const CanRaw: SockProtocol = SockProtocol::Icmp; // Matches libc::CAN_RAW -impl SockProtocol { /// The Controller Area Network broadcast manager protocol /// ([ref](https://docs.kernel.org/networking/can.html#how-to-use-socketcan)) #[cfg(target_os = "linux")] - #[cfg_attr(docsrs, doc(cfg(all())))] #[allow(non_upper_case_globals)] pub const CanBcm: SockProtocol = SockProtocol::NetlinkUserSock; // Matches libc::CAN_BCM + + /// 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(apple_targets)] + #[allow(non_upper_case_globals)] + pub const KextEvent: SockProtocol = SockProtocol::Icmp; // Matches libc::SYSPROTO_EVENT } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] libc_bitflags! { /// Configuration flags for `SO_TIMESTAMPING` interface /// @@ -276,33 +253,23 @@ 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())))] + #[cfg(any(linux_android, + freebsdlike, + netbsdlike, + solarish))] 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())))] + #[cfg(any(linux_android, + freebsdlike, + netbsdlike, + solarish))] 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; } } @@ -333,7 +300,6 @@ libc_bitflags! { /// the calling process and as well as other processes that hold /// file descriptors referring to the same open file description. #[cfg(not(target_os = "aix"))] - #[cfg_attr(docsrs, doc(cfg(all())))] MSG_DONTWAIT; /// Receive flags: Control Data was discarded (buffer too small) MSG_CTRUNC; @@ -352,8 +318,7 @@ libc_bitflags! { /// 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())))] + #[cfg(linux_android)] 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 @@ -362,44 +327,48 @@ libc_bitflags! { /// [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())))] + #[cfg(any(linux_android, freebsdlike, netbsdlike))] 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", + #[cfg(any(linux_android, + freebsdlike, + solarish, + netbsdlike, 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())))] + target_os = "haiku"))] MSG_NOSIGNAL; /// Turns on [`MSG_DONTWAIT`] after the first message has been received (only for /// `recvmmsg()`). - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, + netbsdlike, target_os = "fuchsia", - target_os = "linux", - target_os = "netbsd", - target_os = "freebsd", - target_os = "openbsd", - target_os = "solaris"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + target_os = "freebsd"))] MSG_WAITFORONE; } } +#[cfg(target_os = "freebsd")] +libc_enum! { + /// A selector for which clock to use when generating packet timestamps. + /// Used when setting [`TsClock`](crate::sys::socket::sockopt::TsClock) on a socket. + /// (For more details, see [setsockopt(2)](https://man.freebsd.org/cgi/man.cgi?setsockopt)). + #[repr(i32)] + #[non_exhaustive] + pub enum SocketTimestamp { + /// Microsecond resolution, realtime. This is the default. + SO_TS_REALTIME_MICRO, + /// Sub-nanosecond resolution, realtime. + SO_TS_BINTIME, + /// Nanosecond resolution, realtime. + SO_TS_REALTIME, + /// Nanosecond resolution, monotonic. + SO_TS_MONOTONIC, + } +} + cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { + if #[cfg(linux_android)] { /// Unix credentials of the sending process. /// /// This struct is used with the `SO_PEERCRED` ancillary message @@ -454,7 +423,7 @@ cfg_if! { uc.0 } } - } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] { + } else if #[cfg(freebsdlike)] { /// Unix credentials of the sending process. /// /// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets. @@ -487,7 +456,7 @@ cfg_if! { pub fn groups(&self) -> &[libc::gid_t] { unsafe { std::slice::from_raw_parts( - self.0.cmcred_groups.as_ptr() as *const libc::gid_t, + self.0.cmcred_groups.as_ptr(), self.0.cmcred_ngroups as _ ) } @@ -503,12 +472,7 @@ cfg_if! { } cfg_if! { - if #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "ios" - ))] { + if #[cfg(any(freebsdlike, apple_targets))] { /// Return type of [`LocalPeerCred`](crate::sys::socket::sockopt::LocalPeerCred) #[repr(transparent)] #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -603,8 +567,6 @@ feature! { /// 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 ),* ) => { @@ -617,7 +579,7 @@ macro_rules! cmsg_space { #[inline] #[doc(hidden)] -pub fn cmsg_space<T>() -> usize { +pub const fn cmsg_space<T>() -> usize { // SAFETY: CMSG_SPACE is always safe unsafe { libc::CMSG_SPACE(mem::size_of::<T>() as libc::c_uint) as usize } } @@ -677,7 +639,7 @@ impl<'a> Iterator for CmsgIterator<'a> { } /// A type-safe wrapper around a single control message, as used with -/// [`recvmsg`](#fn.recvmsg). +/// [`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 @@ -692,12 +654,10 @@ 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())))] + #[cfg(linux_android)] ScmCredentials(UnixCredentials), /// Received version of [`ControlMessage::ScmCreds`] - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(freebsdlike)] ScmCreds(UnixCredentials), /// A message of type `SCM_TIMESTAMP`, containing the time the /// packet was received by the kernel. @@ -760,62 +720,44 @@ pub enum ControlMessageOwned { /// A set of nanosecond resolution timestamps /// /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html) - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ScmTimestampsns(Timestamps), /// Nanoseconds resolution timestamp /// /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html) - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] ScmTimestampns(TimeSpec), - #[cfg(any( - target_os = "android", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - ))] + /// Realtime clock timestamp + /// + /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt) + #[cfg(target_os = "freebsd")] + ScmRealtime(TimeSpec), + /// Monotonic clock timestamp + /// + /// [Further reading](https://man.freebsd.org/cgi/man.cgi?setsockopt) + #[cfg(target_os = "freebsd")] + ScmMonotonic(TimeSpec), + #[cfg(any(linux_android, apple_targets, 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(any(linux_android, bsd))] #[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(bsd)] #[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(bsd)] #[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(any(linux_android, target_os = "freebsd"))] #[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(any(linux_android, target_os = "freebsd"))] #[cfg(feature = "net")] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] Ipv6OrigDstAddr(libc::sockaddr_in6), @@ -841,28 +783,31 @@ pub enum ControlMessageOwned { /// /// `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())))] + #[cfg(any(linux_android, target_os = "fuchsia"))] RxqOvfl(u32), /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag. - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] #[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(linux_android)] #[cfg(feature = "net")] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] Ipv6RecvErr(libc::sock_extended_err, Option<sockaddr_in6>), + /// `SOL_TLS` messages of type `TLS_GET_RECORD_TYPE` + #[cfg(any(target_os = "linux"))] + TlsGetRecordType(TlsGetRecordType), + /// Catch-all variant for unimplemented cmsg types. #[doc(hidden)] Unknown(UnknownCmsg), } /// For representing packet timestamps via `SO_TIMESTAMPING` interface -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Timestamps { /// software based timestamp, usually one containing data @@ -873,6 +818,33 @@ pub struct Timestamps { pub hw_raw: TimeSpec, } +/// These constants correspond to TLS 1.2 message types, as defined in +/// RFC 5246, Appendix A.1 +#[cfg(any(target_os = "linux"))] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[repr(u8)] +#[non_exhaustive] +pub enum TlsGetRecordType { + ChangeCipherSpec , + Alert, + Handshake, + ApplicationData, + Unknown(u8), +} + +#[cfg(any(target_os = "linux"))] +impl From<u8> for TlsGetRecordType { + fn from(x: u8) -> Self { + match x { + 20 => TlsGetRecordType::ChangeCipherSpec, + 21 => TlsGetRecordType::Alert, + 22 => TlsGetRecordType::Handshake, + 23 => TlsGetRecordType::ApplicationData, + _ => TlsGetRecordType::Unknown(x), + } + } +} + impl ControlMessageOwned { /// Decodes a `ControlMessageOwned` from raw bytes. /// @@ -885,7 +857,7 @@ impl ControlMessageOwned { #[allow(clippy::cast_ptr_alignment)] unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned { - let p = CMSG_DATA(header); + let p = unsafe { 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 @@ -895,158 +867,151 @@ impl ControlMessageOwned { 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)); + unsafe { + 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"))] + #[cfg(linux_android)] (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => { - let cred: libc::ucred = ptr::read_unaligned(p as *const _); + let cred: libc::ucred = unsafe { ptr::read_unaligned(p as *const _) }; ControlMessageOwned::ScmCredentials(cred.into()) } - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(freebsdlike)] (libc::SOL_SOCKET, libc::SCM_CREDS) => { - let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _); + let cred: libc::cmsgcred = unsafe { ptr::read_unaligned(p as *const _) }; ControlMessageOwned::ScmCreds(cred.into()) } #[cfg(not(any(target_os = "aix", target_os = "haiku")))] (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => { - let tv: libc::timeval = ptr::read_unaligned(p as *const _); + let tv: libc::timeval = unsafe { ptr::read_unaligned(p as *const _) }; ControlMessageOwned::ScmTimestamp(TimeVal::from(tv)) }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] (libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => { - let ts: libc::timespec = ptr::read_unaligned(p as *const _); + let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) }; ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts)) } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(target_os = "freebsd")] + (libc::SOL_SOCKET, libc::SCM_REALTIME) => { + let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) }; + ControlMessageOwned::ScmRealtime(TimeSpec::from(ts)) + } + #[cfg(target_os = "freebsd")] + (libc::SOL_SOCKET, libc::SCM_MONOTONIC) => { + let ts: libc::timespec = unsafe { ptr::read_unaligned(p as *const _) }; + ControlMessageOwned::ScmMonotonic(TimeSpec::from(ts)) + } + #[cfg(linux_android)] (libc::SOL_SOCKET, libc::SCM_TIMESTAMPING) => { let tp = p as *const libc::timespec; - let ts: libc::timespec = ptr::read_unaligned(tp); + let ts: libc::timespec = unsafe { ptr::read_unaligned(tp) }; let system = TimeSpec::from(ts); - let ts: libc::timespec = ptr::read_unaligned(tp.add(1)); + let ts: libc::timespec = unsafe { ptr::read_unaligned(tp.add(1)) }; let hw_trans = TimeSpec::from(ts); - let ts: libc::timespec = ptr::read_unaligned(tp.add(2)); + let ts: libc::timespec = unsafe { 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(any(target_os = "freebsd", linux_android, apple_targets))] #[cfg(feature = "net")] (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => { - let info = ptr::read_unaligned(p as *const libc::in6_pktinfo); + let info = unsafe { 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(any(linux_android, apple_targets, target_os = "netbsd"))] #[cfg(feature = "net")] (libc::IPPROTO_IP, libc::IP_PKTINFO) => { - let info = ptr::read_unaligned(p as *const libc::in_pktinfo); + let info = unsafe { 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(bsd)] #[cfg(feature = "net")] (libc::IPPROTO_IP, libc::IP_RECVIF) => { - let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl); + let dl = unsafe { 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(bsd)] #[cfg(feature = "net")] (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => { - let dl = ptr::read_unaligned(p as *const libc::in_addr); + let dl = unsafe { ptr::read_unaligned(p as *const libc::in_addr) }; ControlMessageOwned::Ipv4RecvDstAddr(dl) }, - #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] + #[cfg(any(linux_android, target_os = "freebsd"))] #[cfg(feature = "net")] (libc::IPPROTO_IP, libc::IP_ORIGDSTADDR) => { - let dl = ptr::read_unaligned(p as *const libc::sockaddr_in); + let dl = unsafe { 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 _); + let gso_size: u16 = unsafe { ptr::read_unaligned(p as *const _) }; ControlMessageOwned::UdpGroSegments(gso_size) }, - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_android, target_os = "fuchsia"))] (libc::SOL_SOCKET, libc::SO_RXQ_OVFL) => { - let drop_counter = ptr::read_unaligned(p as *const u32); + let drop_counter = unsafe { ptr::read_unaligned(p as *const u32) }; ControlMessageOwned::RxqOvfl(drop_counter) }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] #[cfg(feature = "net")] (libc::IPPROTO_IP, libc::IP_RECVERR) => { - let (err, addr) = Self::recv_err_helper::<sockaddr_in>(p, len); + let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in>(p, len) }; ControlMessageOwned::Ipv4RecvErr(err, addr) }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] #[cfg(feature = "net")] (libc::IPPROTO_IPV6, libc::IPV6_RECVERR) => { - let (err, addr) = Self::recv_err_helper::<sockaddr_in6>(p, len); + let (err, addr) = unsafe { Self::recv_err_helper::<sockaddr_in6>(p, len) }; ControlMessageOwned::Ipv6RecvErr(err, addr) }, - #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] + #[cfg(any(linux_android, target_os = "freebsd"))] #[cfg(feature = "net")] (libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR) => { - let dl = ptr::read_unaligned(p as *const libc::sockaddr_in6); + let dl = unsafe { ptr::read_unaligned(p as *const libc::sockaddr_in6) }; ControlMessageOwned::Ipv6OrigDstAddr(dl) }, + #[cfg(any(target_os = "linux"))] + (libc::SOL_TLS, libc::TLS_GET_RECORD_TYPE) => { + let content_type = unsafe { ptr::read_unaligned(p as *const u8) }; + ControlMessageOwned::TlsGetRecordType(content_type.into()) + }, (_, _) => { - let sl = std::slice::from_raw_parts(p, len); + let sl = unsafe { std::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(linux_android)] #[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); + let err = unsafe { 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; + let addrp = unsafe { libc::SO_EE_OFFENDER(ee) as *const T }; - if addrp.offset(1) as usize - (p as usize) > len { + if unsafe { addrp.offset(1) } as usize - (p as usize) > len { (err, None) } else { - (err, Some(ptr::read_unaligned(addrp))) + (err, Some(unsafe { 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. +/// A type-safe zero-copy wrapper around a single control message, as used with +/// [`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)] @@ -1074,8 +1039,7 @@ pub enum ControlMessage<'a> { /// /// 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())))] + #[cfg(linux_android)] ScmCredentials(&'a UnixCredentials), /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of /// a process connected to the socket. @@ -1089,41 +1053,28 @@ pub enum ControlMessage<'a> { /// /// 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())))] + #[cfg(freebsdlike)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] AlgSetAeadAssoclen(&'a u32), /// UDP GSO makes it possible for applications to generate network packets @@ -1139,51 +1090,52 @@ pub enum ControlMessage<'a> { #[cfg_attr(docsrs, doc(cfg(feature = "net")))] UdpGsoSegments(&'a u16), - /// Configure the sending addressing and interface for v4 + /// 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(any(linux_android, target_os = "netbsd", apple_targets))] #[cfg(feature = "net")] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] Ipv4PacketInfo(&'a libc::in_pktinfo), - /// Configure the sending addressing and interface for v6 + /// 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", + #[cfg(any(linux_android, target_os = "netbsd", target_os = "freebsd", - target_os = "android", - target_os = "ios",))] + apple_targets))] #[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(any(freebsdlike, netbsdlike))] #[cfg(feature = "net")] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] Ipv4SendSrcAddr(&'a libc::in_addr), + /// Configure the hop limit for v6 multicast traffic. + /// + /// Set the IPv6 hop limit for this message. The argument is an integer + /// between 0 and 255. A value of -1 will set the hop limit to the route + /// default if possible on the interface. Without this cmsg, packets sent + /// with sendmsg have a hop limit of 1 and will not leave the local network. + /// For further information, please refer to the + /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page. + #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))] + #[cfg(feature = "net")] + #[cfg_attr(docsrs, doc(cfg(feature = "net")))] + Ipv6HopLimit(&'a libc::c_int), + /// 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())))] + #[cfg(any(linux_android, target_os = "fuchsia"))] RxqOvfl(&'a u32), /// Configure the transmission time of packets. @@ -1227,18 +1179,18 @@ impl<'a> ControlMessage<'a> { ControlMessage::ScmRights(fds) => { fds as *const _ as *const u8 }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::ScmCredentials(creds) => { &creds.0 as *const libc::ucred as *const u8 } - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(freebsdlike)] 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"))] + #[cfg(linux_android)] ControlMessage::AlgSetIv(iv) => { #[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501 let af_alg_iv = libc::af_alg_iv { @@ -1263,11 +1215,11 @@ impl<'a> ControlMessage<'a> { return }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::AlgSetOp(op) => { op as *const _ as *const u8 }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::AlgSetAeadAssoclen(len) => { len as *const _ as *const u8 }, @@ -1276,21 +1228,20 @@ impl<'a> ControlMessage<'a> { 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(any(linux_android, target_os = "netbsd", apple_targets))] #[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(any(linux_android, target_os = "netbsd", + target_os = "freebsd", apple_targets))] #[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(any(freebsdlike, netbsdlike))] #[cfg(feature = "net")] ControlMessage::Ipv4SendSrcAddr(addr) => addr as *const _ as *const u8, - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))] + #[cfg(feature = "net")] + ControlMessage::Ipv6HopLimit(limit) => limit as *const _ as *const u8, + #[cfg(any(linux_android, target_os = "fuchsia"))] ControlMessage::RxqOvfl(drop_count) => { drop_count as *const _ as *const u8 }, @@ -1314,23 +1265,23 @@ impl<'a> ControlMessage<'a> { ControlMessage::ScmRights(fds) => { mem::size_of_val(fds) }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::ScmCredentials(creds) => { mem::size_of_val(creds) } - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(freebsdlike)] ControlMessage::ScmCreds => { mem::size_of::<libc::cmsgcred>() } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::AlgSetIv(iv) => { mem::size_of::<&[u8]>() + iv.len() }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::AlgSetOp(op) => { mem::size_of_val(op) }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::AlgSetAeadAssoclen(len) => { mem::size_of_val(len) }, @@ -1339,21 +1290,22 @@ impl<'a> ControlMessage<'a> { 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(any(linux_android, target_os = "netbsd", apple_targets))] #[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(any(linux_android, target_os = "netbsd", + target_os = "freebsd", apple_targets))] #[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(any(freebsdlike, netbsdlike))] #[cfg(feature = "net")] ControlMessage::Ipv4SendSrcAddr(addr) => mem::size_of_val(addr), - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))] + #[cfg(feature = "net")] + ControlMessage::Ipv6HopLimit(limit) => { + mem::size_of_val(limit) + }, + #[cfg(any(linux_android, target_os = "fuchsia"))] ControlMessage::RxqOvfl(drop_count) => { mem::size_of_val(drop_count) }, @@ -1368,31 +1320,30 @@ impl<'a> ControlMessage<'a> { fn cmsg_level(&self) -> libc::c_int { match *self { ControlMessage::ScmRights(_) => libc::SOL_SOCKET, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET, - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(freebsdlike)] ControlMessage::ScmCreds => libc::SOL_SOCKET, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] 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(any(linux_android, target_os = "netbsd", apple_targets))] #[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(any(linux_android, target_os = "netbsd", + target_os = "freebsd", apple_targets))] #[cfg(feature = "net")] ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6, - #[cfg(any(target_os = "netbsd", target_os = "freebsd", - target_os = "openbsd", target_os = "dragonfly"))] + #[cfg(any(freebsdlike, netbsdlike))] #[cfg(feature = "net")] ControlMessage::Ipv4SendSrcAddr(_) => libc::IPPROTO_IP, - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))] + #[cfg(feature = "net")] + ControlMessage::Ipv6HopLimit(_) => libc::IPPROTO_IPV6, + #[cfg(any(linux_android, target_os = "fuchsia"))] ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET, #[cfg(target_os = "linux")] ControlMessage::TxTime(_) => libc::SOL_SOCKET, @@ -1403,19 +1354,19 @@ impl<'a> ControlMessage<'a> { fn cmsg_type(&self) -> libc::c_int { match *self { ControlMessage::ScmRights(_) => libc::SCM_RIGHTS, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS, - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(freebsdlike)] ControlMessage::ScmCreds => libc::SCM_CREDS, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::AlgSetIv(_) => { libc::ALG_SET_IV }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::AlgSetOp(_) => { libc::ALG_SET_OP }, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] ControlMessage::AlgSetAeadAssoclen(_) => { libc::ALG_SET_AEAD_ASSOCLEN }, @@ -1424,21 +1375,20 @@ impl<'a> ControlMessage<'a> { ControlMessage::UdpGsoSegments(_) => { libc::UDP_SEGMENT }, - #[cfg(any(target_os = "linux", target_os = "macos", - target_os = "netbsd", target_os = "android", - target_os = "ios",))] + #[cfg(any(linux_android, target_os = "netbsd", apple_targets))] #[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(any(linux_android, target_os = "netbsd", + target_os = "freebsd", apple_targets))] #[cfg(feature = "net")] ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO, - #[cfg(any(target_os = "netbsd", target_os = "freebsd", - target_os = "openbsd", target_os = "dragonfly"))] + #[cfg(any(freebsdlike, netbsdlike))] #[cfg(feature = "net")] ControlMessage::Ipv4SendSrcAddr(_) => libc::IP_SENDSRCADDR, - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "haiku"))] + #[cfg(feature = "net")] + ControlMessage::Ipv6HopLimit(_) => libc::IPV6_HOPLIMIT, + #[cfg(any(linux_android, target_os = "fuchsia"))] ControlMessage::RxqOvfl(_) => { libc::SO_RXQ_OVFL }, @@ -1452,10 +1402,12 @@ impl<'a> ControlMessage<'a> { // 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)); + unsafe { + (*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) ); + } } } @@ -1479,7 +1431,7 @@ impl<'a> ControlMessage<'a> { /// let (r, w) = pipe().unwrap(); /// /// let iov = [IoSlice::new(b"hello")]; -/// let fds = [r]; +/// let fds = [r.as_raw_fd()]; /// let cmsg = ControlMessage::ScmRights(&fds); /// sendmsg::<()>(fd1.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), None).unwrap(); /// ``` @@ -1496,7 +1448,7 @@ impl<'a> ControlMessage<'a> { /// let (r, w) = pipe().unwrap(); /// /// let iov = [IoSlice::new(b"hello")]; -/// let fds = [r]; +/// let fds = [r.as_raw_fd()]; /// let cmsg = ControlMessage::ScmRights(&fds); /// sendmsg(fd.as_raw_fd(), &iov, &[cmsg], MsgFlags::empty(), Some(&localhost)).unwrap(); /// ``` @@ -1535,12 +1487,7 @@ pub fn sendmsg<S>(fd: RawFd, iov: &[IoSlice<'_>], cmsgs: &[ControlMessage], /// /// # References /// [`sendmsg`](fn.sendmsg.html) -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", -))] +#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))] pub fn sendmmsg<'a, XS, AS, C, I, S>( fd: RawFd, data: &'a mut MultiHeaders<S>, @@ -1556,7 +1503,7 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>( AS: AsRef<[Option<S>]>, I: AsRef<[IoSlice<'a>]> + 'a, C: AsRef<[ControlMessage<'a>]> + 'a, - S: SockaddrLike + 'a + S: SockaddrLike + 'a, { let mut count = 0; @@ -1564,11 +1511,11 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>( for (i, ((slice, addr), mmsghdr)) in slices.into_iter().zip(addrs.as_ref()).zip(data.items.iter_mut() ).enumerate() { let p = &mut mmsghdr.msg_hdr; - p.msg_iov = slice.as_ref().as_ptr() as *mut libc::iovec; + p.msg_iov = slice.as_ref().as_ptr().cast_mut().cast(); 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 _; + p.msg_name = addr.as_ref().map_or(ptr::null(), S::as_ptr).cast_mut().cast(); // Encode each cmsg. This must happen after initializing the header because // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields. @@ -1583,9 +1530,16 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>( pmhdr = unsafe { CMSG_NXTHDR(p, pmhdr) }; } - count = i+1; + // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders` + // is through the `preallocate` function, which takes an `usize` as an argument to define its size, + // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in + // other words: `count` doesn't overflow + count = i + 1; } + // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the + // maximum number of messages that can be sent safely (i.e. `count` is the minimum of the sizes of `slices`, + // `data.items` and `addrs`) let sent = Errno::result(unsafe { libc::sendmmsg( fd, @@ -1604,12 +1558,7 @@ pub fn sendmmsg<'a, XS, AS, C, I, S>( } -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", -))] +#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))] #[derive(Debug)] /// Preallocated structures needed for [`recvmmsg`] and [`sendmmsg`] functions pub struct MultiHeaders<S> { @@ -1622,12 +1571,7 @@ pub struct MultiHeaders<S> { msg_controllen: usize, } -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", -))] +#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))] impl<S> MultiHeaders<S> { /// Preallocate structure used by [`recvmmsg`] and [`sendmmsg`] takes number of headers to preallocate /// @@ -1652,7 +1596,7 @@ impl<S> MultiHeaders<S> { .enumerate() .map(|(ix, address)| { let (ptr, cap) = match &mut cmsg_buffers { - Some(v) => ((&mut v[ix * msg_controllen] as *mut u8), msg_controllen), + Some(v) => (&mut v[ix * msg_controllen] as *mut u8, msg_controllen), None => (std::ptr::null_mut(), 0), }; let msg_hdr = unsafe { pack_mhdr_to_receive(std::ptr::null_mut(), 0, ptr, cap, address.as_mut_ptr()) }; @@ -1697,12 +1641,7 @@ impl<S> MultiHeaders<S> { // 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", -))] +#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))] pub fn recvmmsg<'a, XS, S, I>( fd: RawFd, data: &'a mut MultiHeaders<S>, @@ -1711,14 +1650,19 @@ pub fn recvmmsg<'a, XS, S, I>( mut timeout: Option<crate::sys::time::TimeSpec>, ) -> crate::Result<MultiResults<'a, S>> where - XS: IntoIterator<Item = &'a I>, - I: AsRef<[IoSliceMut<'a>]> + 'a, + XS: IntoIterator<Item = &'a mut I>, + I: AsMut<[IoSliceMut<'a>]> + 'a, { let mut count = 0; for (i, (slice, mmsghdr)) in slices.into_iter().zip(data.items.iter_mut()).enumerate() { let 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_iov = slice.as_mut().as_mut_ptr().cast(); + p.msg_iovlen = slice.as_mut().len() as _; + + // Doing an unchecked addition is alright here, as the only way to obtain an instance of `MultiHeaders` + // is through the `preallocate` function, which takes an `usize` as an argument to define its size, + // which also provides an upper bound for the size of this zipped iterator. Thus, `i < usize::MAX` or in + // other words: `count` doesn't overflow count = i + 1; } @@ -1726,6 +1670,8 @@ where .as_mut() .map_or_else(std::ptr::null_mut, |t| t as *mut _ as *mut libc::timespec); + // SAFETY: all pointers are guaranteed to be valid for the scope of this function. `count` does represent the + // maximum number of messages that can be received safely (i.e. `count` is the minimum of the sizes of `slices` and `data.items`) let received = Errno::result(unsafe { libc::recvmmsg( fd, @@ -1743,16 +1689,9 @@ where }) } -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", -))] -#[derive(Debug)] /// Iterator over results of [`recvmmsg`]/[`sendmmsg`] -/// -/// +#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))] +#[derive(Debug)] pub struct MultiResults<'a, S> { // preallocated structures rmm: &'a MultiHeaders<S>, @@ -1760,12 +1699,7 @@ pub struct MultiResults<'a, S> { received: usize, } -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", -))] +#[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))] impl<'a, S> Iterator for MultiResults<'a, S> where S: Copy + SockaddrLike, @@ -1838,108 +1772,6 @@ impl<'a> Iterator for IoSliceIterator<'a> { } } -// 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; - use std::os::unix::io::AsRawFd; - - #[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.as_raw_fd(), &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.as_raw_fd(), &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.as_raw_fd(), &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, @@ -1951,19 +1783,23 @@ unsafe fn read_mhdr<'a, 'i, S>( // The cast is not unnecessary on all platforms. #[allow(clippy::unnecessary_cast)] let cmsghdr = { - if mhdr.msg_controllen > 0 { + let ptr = 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) + unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) } } else { ptr::null() - }.as_ref() + }; + + unsafe { + ptr.as_ref() + } }; // Ignore errors if this socket address has statically-known length // // This is to ensure that unix socket addresses have their length set appropriately. - let _ = address.set_length(mhdr.msg_namelen as usize); + let _ = unsafe { address.set_length(mhdr.msg_namelen as usize) }; RecvMsg { bytes: r as usize, @@ -2000,14 +1836,16 @@ unsafe fn pack_mhdr_to_receive<S>( // initialize it. let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed(); let p = mhdr.as_mut_ptr(); - (*p).msg_name = address 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() + unsafe { + (*p).msg_name = address 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>( @@ -2025,7 +1863,7 @@ fn pack_mhdr_to_send<'a, I, C, S>( // The message header must be initialized before the individual cmsgs. let cmsg_ptr = if capacity > 0 { - cmsg_buffer.as_mut_ptr() as *mut c_void + cmsg_buffer.as_mut_ptr().cast() } else { ptr::null_mut() }; @@ -2035,11 +1873,11 @@ fn pack_mhdr_to_send<'a, I, C, S>( // 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_name = addr.map(S::as_ptr).unwrap_or(ptr::null()).cast_mut().cast(); (*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_iov = iov.as_ref().as_ptr().cast_mut().cast(); (*p).msg_iovlen = iov.as_ref().len() as _; (*p).msg_control = cmsg_ptr; (*p).msg_controllen = capacity as _; @@ -2166,17 +2004,51 @@ pub fn socketpair<T: Into<Option<SockProtocol>>>( Errno::result(res)?; // Safe because socketpair returned success. - unsafe { - Ok((OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1]))) + unsafe { Ok((OwnedFd::from_raw_fd(fds[0]), OwnedFd::from_raw_fd(fds[1]))) } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Backlog(i32); + +impl Backlog { + /// Sets the listen queue size to system `SOMAXCONN` value + pub const MAXCONN: Self = Self(libc::SOMAXCONN); + /// Sets the listen queue size to -1 for system supporting it + #[cfg(any(target_os = "linux", target_os = "freebsd"))] + pub const MAXALLOWABLE: Self = Self(-1); + + /// Create a `Backlog`, an `EINVAL` will be returned if `val` is invalid. + pub fn new<I: Into<i32>>(val: I) -> Result<Self> { + cfg_if! { + if #[cfg(any(target_os = "linux", target_os = "freebsd"))] { + const MIN: i32 = -1; + } else { + const MIN: i32 = 0; + } + } + + let val = val.into(); + + if !(MIN..Self::MAXCONN.0).contains(&val) { + return Err(Errno::EINVAL); + } + + Ok(Self(val)) + } +} + +impl From<Backlog> for i32 { + fn from(backlog: Backlog) -> Self { + backlog.0 } } /// Listen for connections on a socket /// /// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html) -pub fn listen<F: AsFd>(sock: &F, backlog: usize) -> Result<()> { +pub fn listen<F: AsFd>(sock: &F, backlog: Backlog) -> Result<()> { let fd = sock.as_fd().as_raw_fd(); - let res = unsafe { libc::listen(fd, backlog as c_int) }; + let res = unsafe { libc::listen(fd, backlog.into()) }; Errno::result(res).map(drop) } @@ -2211,14 +2083,12 @@ pub fn accept(sockfd: RawFd) -> Result<RawFd> { target_arch = "x86_64" ) ), - target_os = "dragonfly", + freebsdlike, + netbsdlike, target_os = "emscripten", - target_os = "freebsd", target_os = "fuchsia", - target_os = "illumos", + solarish, target_os = "linux", - target_os = "netbsd", - target_os = "openbsd" ))] pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> { let res = unsafe { @@ -2245,7 +2115,7 @@ pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> { unsafe { let ret = libc::recv( sockfd, - buf.as_mut_ptr() as *mut c_void, + buf.as_mut_ptr().cast(), buf.len() as size_t, flags.bits(), ); @@ -2269,20 +2139,14 @@ pub fn recvfrom<T: SockaddrLike>( let ret = Errno::result(libc::recvfrom( sockfd, - buf.as_mut_ptr() as *mut c_void, + buf.as_mut_ptr().cast(), buf.len() as size_t, 0, - addr.as_mut_ptr() as *mut sockaddr, + addr.as_mut_ptr().cast(), &mut len as *mut socklen_t, ))? as usize; - Ok(( - ret, - T::from_raw( - addr.assume_init().as_ptr(), - Some(len), - ), - )) + Ok((ret, T::from_raw(addr.assume_init().as_ptr(), Some(len)))) } } @@ -2298,7 +2162,7 @@ pub fn sendto( let ret = unsafe { libc::sendto( fd, - buf.as_ptr() as *const c_void, + buf.as_ptr().cast(), buf.len() as size_t, flags.bits(), addr.as_ptr(), @@ -2314,12 +2178,7 @@ pub fn sendto( /// [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(), - ) + libc::send(fd, buf.as_ptr().cast(), buf.len() as size_t, flags.bits()) }; Errno::result(ret).map(|r| r as usize) @@ -2386,8 +2245,7 @@ pub fn getpeername<T: SockaddrLike>(fd: RawFd) -> Result<T> { let mut addr = mem::MaybeUninit::<T>::uninit(); let mut len = T::size(); - let ret = - libc::getpeername(fd, addr.as_mut_ptr() as *mut sockaddr, &mut len); + let ret = libc::getpeername(fd, addr.as_mut_ptr().cast(), &mut len); Errno::result(ret)?; @@ -2403,8 +2261,7 @@ pub fn getsockname<T: SockaddrLike>(fd: RawFd) -> Result<T> { let mut addr = mem::MaybeUninit::<T>::uninit(); let mut len = T::size(); - let ret = - libc::getsockname(fd, addr.as_mut_ptr() as *mut sockaddr, &mut len); + let ret = libc::getsockname(fd, addr.as_mut_ptr().cast(), &mut len); Errno::result(ret)?; @@ -2439,27 +2296,3 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> { } } -#[cfg(test)] -mod tests { - #[cfg(not(target_os = "redox"))] - #[test] - fn can_use_cmsg_space() { - let _ = cmsg_space!(u8); - } - - #[cfg(not(any( - target_os = "redox", - target_os = "linux", - target_os = "android" - )))] - #[test] - fn can_open_routing_socket() { - let _ = super::socket( - super::AddressFamily::Route, - super::SockType::Raw, - super::SockFlag::empty(), - None, - ) - .expect("Failed to open routing socket"); - } -} diff --git a/third_party/rust/nix/src/sys/socket/sockopt.rs b/third_party/rust/nix/src/sys/socket/sockopt.rs index 44f3ebbc1d..4357695f56 100644 --- a/third_party/rust/nix/src/sys/socket/sockopt.rs +++ b/third_party/rust/nix/src/sys/socket/sockopt.rs @@ -7,7 +7,6 @@ use cfg_if::cfg_if; use libc::{self, c_int, c_void, socklen_t}; use std::ffi::{OsStr, OsString}; use std::mem::{self, MaybeUninit}; -#[cfg(target_family = "unix")] use std::os::unix::ffi::OsStrExt; use std::os::unix::io::{AsFd, AsRawFd}; @@ -128,7 +127,7 @@ macro_rules! getsockopt_impl { /// 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`), +/// (`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 `getsockopt`/`setsockopt` call. /// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`, @@ -261,7 +260,7 @@ sockopt_impl!( libc::SO_REUSEADDR, bool ); -#[cfg(not(any(target_os = "illumos", target_os = "solaris")))] +#[cfg(not(solarish))] sockopt_impl!( /// Permits multiple AF_INET or AF_INET6 sockets to be bound to an /// identical socket address. @@ -318,7 +317,7 @@ sockopt_impl!( super::IpMembershipRequest ); cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { + if #[cfg(linux_android)] { #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -329,14 +328,7 @@ cfg_if! { #[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"))] { + } else if #[cfg(any(bsd, solarish))] { #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -365,6 +357,17 @@ sockopt_impl!( #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] + /// Set or read the hop limit value of outgoing IPv6 multicast packets for + /// this socket. + Ipv6MulticastHops, + Both, + libc::IPPROTO_IPV6, + libc::IPV6_MULTICAST_HOPS, + libc::c_int +); +#[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, @@ -408,7 +411,7 @@ sockopt_impl!( libc::IPV6_TCLASS, libc::c_int ); -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_android, target_os = "fuchsia"))] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -420,6 +423,20 @@ sockopt_impl!( libc::IP_FREEBIND, bool ); +#[cfg(linux_android)] +#[cfg(feature = "net")] +sockopt_impl!( + #[cfg_attr(docsrs, doc(cfg(feature = "net")))] + /// If enabled, the kernel will not reserve an ephemeral port when binding + /// socket with a port number of 0. The port will later be automatically + /// chosen at connect time, in a way that allows sharing a source port as + /// long as the 4-tuple is unique. + IpBindAddressNoPort, + Both, + libc::IPPROTO_IP, + libc::IP_BIND_ADDRESS_NO_PORT, + bool +); sockopt_impl!( /// Specify the receiving timeout until reporting an error. ReceiveTimeout, @@ -477,12 +494,7 @@ sockopt_impl!( libc::SO_KEEPALIVE, bool ); -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "ios" -))] +#[cfg(any(freebsdlike, apple_targets))] sockopt_impl!( /// Get the credentials of the peer process of a connected unix domain /// socket. @@ -492,7 +504,7 @@ sockopt_impl!( libc::LOCAL_PEERCRED, super::XuCred ); -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(apple_targets)] sockopt_impl!( /// Get the PID of the peer process of a connected unix domain socket. LocalPeerPid, @@ -501,7 +513,7 @@ sockopt_impl!( libc::LOCAL_PEERPID, libc::c_int ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] sockopt_impl!( /// Return the credentials of the foreign process connected to this socket. PeerCredentials, @@ -510,7 +522,18 @@ sockopt_impl!( libc::SO_PEERCRED, super::UnixCredentials ); -#[cfg(any(target_os = "ios", target_os = "macos"))] +#[cfg(target_os = "freebsd")] +#[cfg(feature = "net")] +sockopt_impl!( + #[cfg_attr(docsrs, doc(cfg(feature = "net")))] + /// Get backlog limit of the socket + ListenQLimit, + GetOnly, + libc::SOL_SOCKET, + libc::SO_LISTENQLIMIT, + u32 +); +#[cfg(apple_targets)] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -522,12 +545,7 @@ sockopt_impl!( libc::TCP_KEEPALIVE, u32 ); -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux" -))] +#[cfg(any(freebsdlike, linux_android))] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -540,7 +558,7 @@ sockopt_impl!( u32 ); cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { + if #[cfg(linux_android)] { sockopt_impl!( /// The maximum segment size for outgoing TCP packets. TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32); @@ -550,7 +568,11 @@ cfg_if! { TcpMaxSeg, GetOnly, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32); } } -#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "redox")))] +#[cfg(not(any( + target_os = "openbsd", + target_os = "haiku", + target_os = "redox" +)))] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -562,7 +584,7 @@ sockopt_impl!( libc::TCP_KEEPCNT, u32 ); -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_android, target_os = "fuchsia"))] sockopt_impl!( #[allow(missing_docs)] // Not documented by Linux! @@ -572,7 +594,11 @@ sockopt_impl!( libc::TCP_REPAIR, u32 ); -#[cfg(not(any(target_os = "openbsd", target_os = "haiku", target_os = "redox")))] +#[cfg(not(any( + target_os = "openbsd", + target_os = "haiku", + target_os = "redox" +)))] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -596,6 +622,26 @@ sockopt_impl!( libc::TCP_USER_TIMEOUT, u32 ); +#[cfg(linux_android)] +#[cfg(feature = "net")] +sockopt_impl!( + #[cfg_attr(docsrs, doc(cfg(feature = "net")))] + /// Enables TCP Fast Open (RFC 7413) on a connecting socket. If a fast open + /// cookie is not available (first attempt to connect), `connect` syscall + /// will behave as usual, except for internally trying to solicit a cookie + /// from remote peer. When cookie is available, the next `connect` syscall + /// will immediately succeed without actually establishing TCP connection. + /// The connection establishment will be defered till the next `write` or + /// `sendmsg` syscalls on the socket, allowing TCP prtocol to establish + /// connection and send data in the same packets. Note: calling `read` right + /// after `connect` without `write` on the socket will cause the blocking + /// socket to be blocked forever. + TcpFastOpenConnect, + Both, + libc::IPPROTO_TCP, + libc::TCP_FASTOPEN_CONNECT, + bool +); sockopt_impl!( /// Sets or gets the maximum socket receive buffer in bytes. RcvBuf, @@ -612,7 +658,7 @@ sockopt_impl!( libc::SO_SNDBUF, usize ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] 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 @@ -623,7 +669,7 @@ sockopt_impl!( libc::SO_RCVBUFFORCE, usize ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] 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 @@ -652,7 +698,7 @@ sockopt_impl!( libc::SO_ACCEPTCONN, bool ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] sockopt_impl!( /// Bind this socket to a particular device like “eth0”. BindToDevice, @@ -661,7 +707,7 @@ sockopt_impl!( libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]> ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -673,7 +719,7 @@ sockopt_impl!( libc::SO_ORIGINAL_DST, libc::sockaddr_in ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] sockopt_impl!( #[allow(missing_docs)] // Not documented by Linux! @@ -683,7 +729,7 @@ sockopt_impl!( libc::IP6T_SO_ORIGINAL_DST, libc::sockaddr_in6 ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] sockopt_impl!( /// Specifies exact type of timestamping information collected by the kernel /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html) @@ -693,7 +739,7 @@ sockopt_impl!( libc::SO_TIMESTAMPING, super::TimestampingFlag ); -#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "redox")))] +#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "hurd", target_os = "redox")))] sockopt_impl!( /// Enable or disable the receiving of the `SO_TIMESTAMP` control message. ReceiveTimestamp, @@ -702,7 +748,7 @@ sockopt_impl!( libc::SO_TIMESTAMP, bool ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] sockopt_impl!( /// Enable or disable the receiving of the `SO_TIMESTAMPNS` control message. ReceiveTimestampns, @@ -719,9 +765,9 @@ sockopt_impl!( Both, libc::SOL_SOCKET, libc::SO_TS_CLOCK, - i32 + super::SocketTimestamp ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -806,7 +852,7 @@ sockopt_impl!( libc::SO_MARK, u32 ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] sockopt_impl!( /// Enable or disable the receiving of the `SCM_CREDENTIALS` control /// message. @@ -828,13 +874,7 @@ sockopt_impl!( 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(any(linux_android, apple_targets, target_os = "netbsd"))] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -846,15 +886,7 @@ sockopt_impl!( 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(any(linux_android, target_os = "freebsd", apple_targets, netbsdlike))] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -866,13 +898,7 @@ sockopt_impl!( libc::IPV6_RECVPKTINFO, bool ); -#[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] +#[cfg(bsd)] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -884,13 +910,7 @@ sockopt_impl!( libc::IP_RECVIF, bool ); -#[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] +#[cfg(bsd)] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -902,7 +922,7 @@ sockopt_impl!( libc::IP_RECVDSTADDR, bool ); -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +#[cfg(any(linux_android, target_os = "freebsd"))] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -948,7 +968,7 @@ sockopt_impl!( libc::SO_TXTIME, libc::sock_txtime ); -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_android, target_os = "fuchsia"))] 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 @@ -969,7 +989,7 @@ sockopt_impl!( libc::IPV6_V6ONLY, bool ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] sockopt_impl!( /// Enable extended reliable error message passing. Ipv4RecvErr, @@ -978,7 +998,7 @@ sockopt_impl!( libc::IP_RECVERR, bool ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] sockopt_impl!( /// Control receiving of asynchronous error options. Ipv6RecvErr, @@ -987,7 +1007,7 @@ sockopt_impl!( libc::IPV6_RECVERR, bool ); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] sockopt_impl!( /// Fetch the current system-estimated Path MTU. IpMtu, @@ -996,7 +1016,7 @@ sockopt_impl!( libc::IP_MTU, libc::c_int ); -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +#[cfg(any(linux_android, target_os = "freebsd"))] sockopt_impl!( /// Set or retrieve the current time-to-live field that is used in every /// packet sent from this socket. @@ -1006,7 +1026,7 @@ sockopt_impl!( libc::IP_TTL, libc::c_int ); -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +#[cfg(any(linux_android, target_os = "freebsd"))] sockopt_impl!( /// Set the unicast hop limit for the socket. Ipv6Ttl, @@ -1015,7 +1035,7 @@ sockopt_impl!( libc::IPV6_UNICAST_HOPS, libc::c_int ); -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +#[cfg(any(linux_android, target_os = "freebsd"))] #[cfg(feature = "net")] sockopt_impl!( #[cfg_attr(docsrs, doc(cfg(feature = "net")))] @@ -1027,7 +1047,7 @@ sockopt_impl!( libc::IPV6_ORIGDSTADDR, bool ); -#[cfg(any(target_os = "ios", target_os = "macos"))] +#[cfg(apple_targets)] sockopt_impl!( /// Set "don't fragment packet" flag on the IP packet. IpDontFrag, @@ -1036,12 +1056,7 @@ sockopt_impl!( libc::IP_DONTFRAG, bool ); -#[cfg(any( - target_os = "android", - target_os = "ios", - target_os = "linux", - target_os = "macos", -))] +#[cfg(any(linux_android, apple_targets))] sockopt_impl!( /// Set "don't fragment packet" flag on the IPv6 packet. Ipv6DontFrag, @@ -1053,13 +1068,13 @@ sockopt_impl!( #[allow(missing_docs)] // Not documented by Linux! -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] #[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"))] +#[cfg(linux_android)] impl SetSockOpt for AlgSetAeadAuthSize { type Val = usize; @@ -1079,18 +1094,18 @@ impl SetSockOpt for AlgSetAeadAuthSize { #[allow(missing_docs)] // Not documented by Linux! -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] #[derive(Clone, Debug)] pub struct AlgSetKey<T>(::std::marker::PhantomData<T>); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] impl<T> Default for AlgSetKey<T> { fn default() -> Self { AlgSetKey(Default::default()) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] impl<T> SetSockOpt for AlgSetKey<T> where T: AsRef<[u8]> + Clone, @@ -1103,7 +1118,54 @@ where fd.as_fd().as_raw_fd(), libc::SOL_ALG, libc::ALG_SET_KEY, - val.as_ref().as_ptr() as *const _, + val.as_ref().as_ptr().cast(), + val.as_ref().len() as libc::socklen_t, + ); + Errno::result(res).map(drop) + } + } +} + +/// Set the Upper Layer Protocol (ULP) on the TCP socket. +/// +/// For example, to enable the TLS ULP on a socket, the C function call would be: +/// +/// ```c +/// setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls")); +/// ``` +/// +/// ... and the `nix` equivalent is: +/// +/// ```ignore,rust +/// setsockopt(sock, TcpUlp::default(), b"tls"); +/// ``` +/// +/// Note that the ULP name does not need a trailing NUL terminator (`\0`). +#[cfg(linux_android)] +#[derive(Clone, Debug)] +pub struct TcpUlp<T>(::std::marker::PhantomData<T>); + +#[cfg(linux_android)] +impl<T> Default for TcpUlp<T> { + fn default() -> Self { + TcpUlp(Default::default()) + } +} + +#[cfg(linux_android)] +impl<T> SetSockOpt for TcpUlp<T> +where + T: AsRef<[u8]> + Clone, +{ + type Val = T; + + fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> { + unsafe { + let res = libc::setsockopt( + fd.as_fd().as_raw_fd(), + libc::SOL_TCP, + libc::TCP_ULP, + val.as_ref().as_ptr().cast(), val.as_ref().len() as libc::socklen_t, ); Errno::result(res).map(drop) @@ -1111,6 +1173,113 @@ where } } +/// Value used with the [`TcpTlsTx`] and [`TcpTlsRx`] socket options. +#[cfg(target_os = "linux")] +#[derive(Copy, Clone, Debug)] +pub enum TlsCryptoInfo { + /// AES-128-GCM + Aes128Gcm(libc::tls12_crypto_info_aes_gcm_128), + + /// AES-256-GCM + Aes256Gcm(libc::tls12_crypto_info_aes_gcm_256), + + /// CHACHA20-POLY1305 + Chacha20Poly1305(libc::tls12_crypto_info_chacha20_poly1305), +} + +/// Set the Kernel TLS write parameters on the TCP socket. +/// +/// For example, the C function call would be: +/// +/// ```c +/// setsockopt(sock, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info)); +/// ``` +/// +/// ... and the `nix` equivalent is: +/// +/// ```ignore,rust +/// setsockopt(sock, TcpTlsTx, &crypto_info); +/// ``` +#[cfg(target_os = "linux")] +#[derive(Copy, Clone, Debug)] +pub struct TcpTlsTx; + +#[cfg(target_os = "linux")] +impl SetSockOpt for TcpTlsTx { + type Val = TlsCryptoInfo; + + fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> { + let (ffi_ptr, ffi_len) = match val { + TlsCryptoInfo::Aes128Gcm(crypto_info) => { + (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info)) + } + TlsCryptoInfo::Aes256Gcm(crypto_info) => { + (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info)) + } + TlsCryptoInfo::Chacha20Poly1305(crypto_info) => { + (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info)) + } + }; + unsafe { + let res = libc::setsockopt( + fd.as_fd().as_raw_fd(), + libc::SOL_TLS, + libc::TLS_TX, + ffi_ptr, + ffi_len as libc::socklen_t, + ); + Errno::result(res).map(drop) + } + } +} + +/// Set the Kernel TLS read parameters on the TCP socket. +/// +/// For example, the C function call would be: +/// +/// ```c +/// setsockopt(sock, SOL_TLS, TLS_RX, &crypto_info, sizeof(crypto_info)); +/// ``` +/// +/// ... and the `nix` equivalent is: +/// +/// ```ignore,rust +/// setsockopt(sock, TcpTlsRx, &crypto_info); +/// ``` +#[cfg(target_os = "linux")] +#[derive(Copy, Clone, Debug)] +pub struct TcpTlsRx; + +#[cfg(target_os = "linux")] +impl SetSockOpt for TcpTlsRx { + type Val = TlsCryptoInfo; + + fn set<F: AsFd>(&self, fd: &F, val: &Self::Val) -> Result<()> { + let (ffi_ptr, ffi_len) = match val { + TlsCryptoInfo::Aes128Gcm(crypto_info) => { + (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info)) + } + TlsCryptoInfo::Aes256Gcm(crypto_info) => { + (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info)) + } + TlsCryptoInfo::Chacha20Poly1305(crypto_info) => { + (<*const _>::cast(crypto_info), mem::size_of_val(crypto_info)) + } + }; + unsafe { + let res = libc::setsockopt( + fd.as_fd().as_raw_fd(), + libc::SOL_TLS, + libc::TLS_RX, + ffi_ptr, + ffi_len as libc::socklen_t, + ); + Errno::result(res).map(drop) + } + } +} + + /* * * ===== Accessor helpers ===== @@ -1158,7 +1327,7 @@ impl<T> Get<T> for GetStruct<T> { } fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void + self.val.as_mut_ptr().cast() } fn ffi_len(&mut self) -> *mut socklen_t { @@ -1171,7 +1340,7 @@ impl<T> Get<T> for GetStruct<T> { mem::size_of::<T>(), "invalid getsockopt implementation" ); - self.val.assume_init() + unsafe { self.val.assume_init() } } } @@ -1209,7 +1378,7 @@ impl Get<bool> for GetBool { } fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void + self.val.as_mut_ptr().cast() } fn ffi_len(&mut self) -> *mut socklen_t { @@ -1222,7 +1391,7 @@ impl Get<bool> for GetBool { mem::size_of::<c_int>(), "invalid getsockopt implementation" ); - self.val.assume_init() != 0 + unsafe { self.val.assume_init() != 0 } } } @@ -1243,7 +1412,7 @@ impl<'a> Set<'a, bool> for SetBool { } fn ffi_len(&self) -> socklen_t { - mem::size_of::<c_int>() as socklen_t + mem::size_of_val(&self.val) as socklen_t } } @@ -1262,7 +1431,7 @@ impl Get<u8> for GetU8 { } fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void + self.val.as_mut_ptr().cast() } fn ffi_len(&mut self) -> *mut socklen_t { @@ -1275,7 +1444,7 @@ impl Get<u8> for GetU8 { mem::size_of::<u8>(), "invalid getsockopt implementation" ); - self.val.assume_init() + unsafe { self.val.assume_init() } } } @@ -1294,7 +1463,7 @@ impl<'a> Set<'a, u8> for SetU8 { } fn ffi_len(&self) -> socklen_t { - mem::size_of::<c_int>() as socklen_t + mem::size_of_val(&self.val) as socklen_t } } @@ -1313,7 +1482,7 @@ impl Get<usize> for GetUsize { } fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void + self.val.as_mut_ptr().cast() } fn ffi_len(&mut self) -> *mut socklen_t { @@ -1326,7 +1495,7 @@ impl Get<usize> for GetUsize { mem::size_of::<c_int>(), "invalid getsockopt implementation" ); - self.val.assume_init() as usize + unsafe { self.val.assume_init() as usize } } } @@ -1345,7 +1514,7 @@ impl<'a> Set<'a, usize> for SetUsize { } fn ffi_len(&self) -> socklen_t { - mem::size_of::<c_int>() as socklen_t + mem::size_of_val(&self.val) as socklen_t } } @@ -1364,7 +1533,7 @@ impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> { } fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void + self.val.as_mut_ptr().cast() } fn ffi_len(&mut self) -> *mut socklen_t { @@ -1373,7 +1542,7 @@ impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> { unsafe fn assume_init(self) -> OsString { let len = self.len as usize; - let mut v = self.val.assume_init(); + let mut v = unsafe { self.val.assume_init() }; OsStr::from_bytes(&v.as_mut()[0..len]).to_owned() } } @@ -1391,7 +1560,7 @@ impl<'a> Set<'a, OsString> for SetOsString<'a> { } fn ffi_ptr(&self) -> *const c_void { - self.val.as_bytes().as_ptr() as *const c_void + self.val.as_bytes().as_ptr().cast() } fn ffi_len(&self) -> socklen_t { @@ -1399,72 +1568,3 @@ impl<'a> Set<'a, OsString> for SetOsString<'a> { } } -#[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::*; - - 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); - } - - #[test] - fn is_socket_type_dgram() { - use super::super::*; - - 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); - } - - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - #[test] - fn can_get_listen_on_tcp_socket() { - use super::super::*; - - 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); - } -} diff --git a/third_party/rust/nix/src/sys/stat.rs b/third_party/rust/nix/src/sys/stat.rs index 7e51c03a3f..c5854eec01 100644 --- a/third_party/rust/nix/src/sys/stat.rs +++ b/third_party/rust/nix/src/sys/stat.rs @@ -1,10 +1,6 @@ -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))] +#[cfg(any(apple_targets, target_os = "openbsd"))] pub use libc::c_uint; -#[cfg(any( - target_os = "netbsd", - target_os = "freebsd", - target_os = "dragonfly" -))] +#[cfg(any(target_os = "netbsd", freebsdlike))] pub use libc::c_ulong; pub use libc::stat as FileStat; pub use libc::{dev_t, mode_t}; @@ -43,7 +39,7 @@ libc_bitflags! { S_IXUSR; /// Read write and execute for group. S_IRWXG; - /// Read fr group. + /// Read for group. S_IRGRP; /// Write for group. S_IWGRP; @@ -65,26 +61,14 @@ libc_bitflags! { } } -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "openbsd"))] +#[cfg(any(apple_targets, target_os = "openbsd"))] pub type type_of_file_flag = c_uint; -#[cfg(any( - target_os = "netbsd", - target_os = "freebsd", - target_os = "dragonfly" -))] +#[cfg(any(freebsdlike, target_os = "netbsd"))] 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" -))] +#[cfg(bsd)] 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; @@ -101,7 +85,7 @@ libc_bitflags! { #[cfg(any(target_os = "dragonfly"))] SF_NOHISTORY; /// The file may not be renamed or deleted. - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(freebsdlike)] SF_NOUNLINK; /// Mask of superuser changeable flags SF_SETTABLE; @@ -121,14 +105,13 @@ libc_bitflags! { #[cfg(any(target_os = "dragonfly"))] UF_CACHE; /// File is compressed at the file system level. - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] 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", + apple_targets, ))] UF_HIDDEN; /// The file may not be changed. @@ -138,7 +121,7 @@ libc_bitflags! { #[cfg(any(target_os = "dragonfly"))] UF_NOHISTORY; /// The file may not be renamed or deleted. - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(freebsdlike)] UF_NOUNLINK; /// The file is offline, or has the Windows and CIFS /// `FILE_ATTRIBUTE_OFFLINE` attribute. @@ -162,7 +145,7 @@ libc_bitflags! { #[cfg(any(target_os = "freebsd"))] UF_SYSTEM; /// File renames and deletes are tracked. - #[cfg(any(target_os = "macos", target_os = "ios"))] + #[cfg(apple_targets)] UF_TRACKED; #[cfg(any(target_os = "dragonfly"))] UF_XLINK; @@ -184,20 +167,15 @@ pub fn mknod<P: ?Sized + NixPath>( } /// 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())))] +#[cfg(not(any(apple_targets, target_os = "redox", target_os = "haiku")))] pub fn mknodat<P: ?Sized + NixPath>( - dirfd: RawFd, + dirfd: Option<RawFd>, path: &P, kind: SFlag, perm: Mode, dev: dev_t, ) -> Result<()> { + let dirfd = at_rawfd(dirfd); let res = path.with_nix_path(|cstr| unsafe { libc::mknodat( dirfd, @@ -211,19 +189,16 @@ pub fn mknodat<P: ?Sized + NixPath>( } #[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) @@ -268,12 +243,12 @@ pub fn fstat(fd: RawFd) -> Result<FileStat> { } #[cfg(not(target_os = "redox"))] -#[cfg_attr(docsrs, doc(cfg(all())))] pub fn fstatat<P: ?Sized + NixPath>( - dirfd: RawFd, + dirfd: Option<RawFd>, pathname: &P, f: AtFlags, ) -> Result<FileStat> { + let dirfd = at_rawfd(dirfd); let mut dst = mem::MaybeUninit::uninit(); let res = pathname.with_nix_path(|cstr| unsafe { libc::fstatat( @@ -324,7 +299,6 @@ pub enum FchmodatFlags { /// /// [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, @@ -383,12 +357,10 @@ pub fn utimes<P: ?Sized + NixPath>( #[cfg(any( target_os = "linux", target_os = "haiku", - target_os = "ios", - target_os = "macos", + apple_targets, target_os = "freebsd", target_os = "netbsd" ))] -#[cfg_attr(docsrs, doc(cfg(all())))] pub fn lutimes<P: ?Sized + NixPath>( path: &P, atime: &TimeVal, @@ -404,6 +376,9 @@ pub fn lutimes<P: ?Sized + NixPath>( /// Change the access and modification times of the file specified by a file descriptor. /// +/// If you want to set the timestamp to now, use `TimeSpec::UTIME_NOW`. Use +/// `TimeSpec::UTIME_OMIT` if you don't want to change it. +/// /// # References /// /// [futimens(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html). @@ -436,11 +411,13 @@ pub enum UtimensatFlags { /// `utimes(path, times)`. The latter is a deprecated API so prefer using the /// former if the platforms you care about support it. /// +/// If you want to set the timestamp to now, use `TimeSpec::UTIME_NOW`. Use +/// `TimeSpec::UTIME_OMIT` if you don't want to change 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, @@ -466,12 +443,12 @@ pub fn utimensat<P: ?Sized + NixPath>( } #[cfg(not(target_os = "redox"))] -#[cfg_attr(docsrs, doc(cfg(all())))] pub fn mkdirat<P: ?Sized + NixPath>( - fd: RawFd, + fd: Option<RawFd>, path: &P, mode: Mode, ) -> Result<()> { + let fd = at_rawfd(fd); let res = path.with_nix_path(|cstr| unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) })?; diff --git a/third_party/rust/nix/src/sys/statfs.rs b/third_party/rust/nix/src/sys/statfs.rs index 5111df2e6e..b2315f4ceb 100644 --- a/third_party/rust/nix/src/sys/statfs.rs +++ b/third_party/rust/nix/src/sys/statfs.rs @@ -1,7 +1,7 @@ //! Get filesystem statistics, non-portably //! //! See [`statvfs`](crate::sys::statvfs) for a portable alternative. -#[cfg(not(any(target_os = "linux", target_os = "android")))] +#[cfg(not(linux_android))] use std::ffi::CStr; use std::fmt::{self, Debug}; use std::mem; @@ -9,16 +9,7 @@ use std::os::unix::io::{AsFd, 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" - ) -))] +#[cfg(all(feature = "mount", bsd))] use crate::mount::MntFlags; #[cfg(target_os = "linux")] use crate::sys::statvfs::FsFlags; @@ -26,15 +17,13 @@ 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"))] { + if #[cfg(any(linux_android, target_os = "fuchsia"))] { type type_of_statfs = libc::statfs64; const LIBC_FSTATFS: unsafe extern fn (fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int @@ -62,10 +51,12 @@ pub struct Statfs(type_of_statfs); type fs_type_t = u32; #[cfg(target_os = "android")] type fs_type_t = libc::c_ulong; -#[cfg(all(target_os = "linux", target_arch = "s390x"))] +#[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))] 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 = "ohos"))] +type fs_type_t = libc::c_ulong; #[cfg(all(target_os = "linux", target_env = "uclibc"))] type fs_type_t = libc::c_int; #[cfg(all( @@ -73,6 +64,7 @@ type fs_type_t = libc::c_int; not(any( target_arch = "s390x", target_env = "musl", + target_env = "ohos", target_env = "uclibc" )) ))] @@ -84,6 +76,7 @@ type fs_type_t = libc::__fsword_t; target_os = "android", all(target_os = "linux", target_arch = "s390x"), all(target_os = "linux", target_env = "musl"), + all(target_os = "linux", target_env = "ohos"), all( target_os = "linux", not(any(target_arch = "s390x", target_env = "musl")) @@ -94,206 +87,203 @@ 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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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"))] +#[cfg(linux_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") -))] +#[cfg(all(linux_android, not(target_env = "musl"), not(target_env = "ohos")))] #[allow(missing_docs)] pub const XFS_SUPER_MAGIC: FsType = FsType(libc::XFS_SUPER_MAGIC as fs_type_t); @@ -302,39 +292,33 @@ impl Statfs { #[cfg(not(any( target_os = "openbsd", target_os = "dragonfly", - target_os = "ios", - target_os = "macos" + apple_targets, )))] - #[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())))] + #[cfg(not(linux_android))] 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())))] + #[cfg(apple_targets)] 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())))] + #[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))] pub fn optimal_transfer_size(&self) -> u32 { self.0.f_bsize } @@ -342,9 +326,9 @@ impl Statfs { /// Optimal transfer block size #[cfg(any( target_os = "android", - all(target_os = "linux", target_env = "musl") + all(target_os = "linux", target_env = "musl"), + all(target_os = "linux", target_env = "ohos") ))] - #[cfg_attr(docsrs, doc(cfg(all())))] pub fn optimal_transfer_size(&self) -> libc::c_ulong { self.0.f_bsize } @@ -355,46 +339,41 @@ impl Statfs { not(any( target_arch = "s390x", target_env = "musl", + target_env = "ohos", 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())))] + #[cfg(any(apple_targets, target_os = "openbsd"))] 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())))] + #[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))] pub fn block_size(&self) -> u32 { self.0.f_bsize } @@ -402,7 +381,13 @@ impl Statfs { /// 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 = "ohos"))] pub fn block_size(&self) -> libc::c_ulong { self.0.f_bsize } @@ -410,7 +395,6 @@ impl Statfs { /// 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 } @@ -422,47 +406,34 @@ impl Statfs { not(any( target_arch = "s390x", target_env = "musl", + target_env = "ohos", 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())))] + #[cfg(all(feature = "mount", bsd))] #[allow(clippy::unnecessary_cast)] // Not unnecessary on all arches pub fn flags(&self) -> MntFlags { MntFlags::from_bits_truncate(self.0.f_flags as i32) @@ -472,35 +443,30 @@ impl Statfs { // 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())))] + #[cfg(all(target_os = "linux", target_arch = "s390x", not(target_env = "musl")))] 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 } @@ -511,173 +477,141 @@ impl Statfs { not(any( target_arch = "s390x", target_env = "musl", + target_env = "ohos", 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", + apple_targets, + linux_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", + apple_targets, + linux_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())))] + #[cfg(any(apple_targets, linux_android, target_os = "fuchsia"))] 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", + apple_targets, + linux_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", + apple_targets, + linux_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 } @@ -699,16 +633,7 @@ impl Debug for Statfs { 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" - ) - ))] + #[cfg(all(feature = "mount", bsd))] ds.field("flags", &self.flags()); ds.finish() } @@ -747,107 +672,3 @@ pub fn fstatfs<Fd: AsFd>(fd: Fd) -> Result<Statfs> { .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/third_party/rust/nix/src/sys/statvfs.rs b/third_party/rust/nix/src/sys/statvfs.rs index 35424e5e27..db1abdd4fe 100644 --- a/third_party/rust/nix/src/sys/statvfs.rs +++ b/third_party/rust/nix/src/sys/statvfs.rs @@ -21,44 +21,34 @@ libc_bitflags!( #[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())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] ST_NOEXEC; /// All IO should be done synchronously - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] ST_SYNCHRONOUS; /// Allow mandatory locks on the filesystem - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] ST_NOATIME; /// Do not update access times on files - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"), not(target_env = "ohos"))))] ST_RELATIME; } ); @@ -114,13 +104,18 @@ impl Statvfs { } /// Get the file system id + #[cfg(not(target_os = "hurd"))] pub fn filesystem_id(&self) -> c_ulong { self.0.f_fsid } + /// Get the file system id + #[cfg(target_os = "hurd")] + pub fn filesystem_id(&self) -> u64 { + 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) } @@ -153,20 +148,3 @@ pub fn fstatvfs<Fd: AsFd>(fd: Fd) -> Result<Statvfs> { .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/third_party/rust/nix/src/sys/termios.rs b/third_party/rust/nix/src/sys/termios.rs index ecaa3eaf8f..e006c2f1b0 100644 --- a/third_party/rust/nix/src/sys/termios.rs +++ b/third_party/rust/nix/src/sys/termios.rs @@ -85,28 +85,8 @@ //! //! 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" -)] +#![cfg_attr(bsd, doc = " ```rust,ignore")] +#![cfg_attr(not(bsd), doc = " ```rust")] //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios}; //! # fn main() { //! # let mut t: Termios = unsafe { std::mem::zeroed() }; @@ -118,28 +98,8 @@ //! //! 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" -)] +#![cfg_attr(bsd, doc = " ```rust")] +#![cfg_attr(not(bsd), doc = " ```rust,ignore")] //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios}; //! # fn main() { //! # let mut t: Termios = unsafe { std::mem::zeroed() }; @@ -151,28 +111,8 @@ //! //! 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" -)] +#![cfg_attr(bsd, doc = " ```rust")] +#![cfg_attr(not(bsd), doc = " ```rust,ignore")] //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios}; //! # fn main() { //! # let mut t: Termios = unsafe { std::mem::zeroed() }; @@ -185,28 +125,8 @@ //! 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" -)] +#![cfg_attr(bsd, doc = " ```rust")] +#![cfg_attr(not(bsd), doc = " ```rust,ignore")] //! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios}; //! # fn main() { //! # let mut t: Termios = unsafe { std::mem::zeroed() }; @@ -246,7 +166,7 @@ pub struct Termios { /// 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",))] + #[cfg(linux_android)] pub line_discipline: libc::cc_t, /// Line discipline (see `termios.c_line` documentation) #[cfg(target_os = "haiku")] @@ -266,11 +186,7 @@ impl Termios { 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", - ))] + #[cfg(any(linux_android, target_os = "haiku"))] { termios.c_line = self.line_discipline; } @@ -292,11 +208,7 @@ impl Termios { 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", - ))] + #[cfg(any(linux_android, target_os = "haiku"))] { termios.c_line = self.line_discipline; } @@ -312,11 +224,7 @@ impl Termios { self.control_flags = ControlFlags::from_bits_retain(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", - ))] + #[cfg(any(linux_android, target_os = "haiku"))] { self.line_discipline = termios.c_line; } @@ -332,11 +240,7 @@ impl From<libc::termios> for Termios { 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", - ))] + #[cfg(any(linux_android, target_os = "haiku"))] line_discipline: termios.c_line, } } @@ -356,8 +260,13 @@ libc_enum! { /// /// B0 is special and will disable the port. #[cfg_attr(target_os = "haiku", repr(u8))] - #[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))] - #[cfg_attr(all(not(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64")), not(target_os = "haiku")), repr(u32))] + #[cfg_attr(target_os = "hurd", repr(i32))] + #[cfg_attr(all(apple_targets, target_pointer_width = "64"), repr(u64))] + #[cfg_attr(all( + not(all(apple_targets, target_pointer_width = "64")), + not(target_os = "haiku"), + not(target_os = "hurd") + ), repr(u32))] #[non_exhaustive] pub enum BaudRate { B0, @@ -373,110 +282,62 @@ libc_enum! { 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] 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())))] + #[cfg(bsd)] B28800, B38400, #[cfg(not(target_os = "aix"))] - #[cfg_attr(docsrs, doc(cfg(all())))] B57600, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(bsd)] B76800, #[cfg(not(target_os = "aix"))] - #[cfg_attr(docsrs, doc(cfg(all())))] B115200, - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(solarish)] B153600, #[cfg(not(target_os = "aix"))] - #[cfg_attr(docsrs, doc(cfg(all())))] B230400, - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(solarish)] B307200, - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, + solarish, target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd", - target_os = "solaris"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + target_os = "netbsd"))] B460800, - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] B500000, - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] B576000, - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, + solarish, target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd", - target_os = "solaris"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + target_os = "netbsd"))] B921600, - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] B1000000, - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] B1152000, - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] B1500000, - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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" -))] +#[cfg(bsd)] impl From<BaudRate> for u32 { fn from(b: BaudRate) -> u32 { b as u32 @@ -542,80 +403,57 @@ libc_enum! { } // 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 { - #[cfg(not(target_os = "aix"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(not(any(target_os = "aix", target_os = "haiku")))] VDISCARD, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "aix", - target_os = "solaris"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(any(bsd, + solarish, + target_os = "aix"))] 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())))] + #[cfg(any(freebsdlike, solarish))] VERASE2, VINTR, VKILL, + #[cfg(not(target_os = "haiku"))] VLNEXT, #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"), - target_os = "illumos", target_os = "solaris", target_os = "aix")))] - #[cfg_attr(docsrs, doc(cfg(all())))] + solarish, target_os = "aix", target_os = "haiku")))] VMIN, VQUIT, + #[cfg(not(target_os = "haiku"))] 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())))] + #[cfg(any(bsd, solarish))] 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())))] + #[cfg(any(solarish, target_os = "haiku"))] VSWTCH, #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"), - target_os = "illumos", target_os = "solaris", target_os = "aix")))] - #[cfg_attr(docsrs, doc(cfg(all())))] + solarish, target_os = "aix", target_os = "haiku")))] VTIME, - #[cfg(not(target_os = "aix"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(not(any(target_os = "aix", target_os = "haiku")))] 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", + solarish, target_os = "aix", + target_os = "haiku", ))] impl SpecialCharacterIndices { pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF; @@ -623,17 +461,7 @@ impl SpecialCharacterIndices { } pub use libc::NCCS; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "aix", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" -))] -#[cfg_attr(docsrs, doc(cfg(all())))] +#[cfg(any(linux_android, target_os = "aix", bsd))] pub use libc::_POSIX_VDISABLE; libc_bitflags! { @@ -651,13 +479,10 @@ libc_bitflags! { 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())))] + #[cfg(any(linux_android, apple_targets))] IUTF8; } } @@ -666,209 +491,119 @@ libc_bitflags! { /// Flags for configuring the output mode of a terminal pub struct OutputFlags: tcflag_t { OPOST; - #[cfg(any(target_os = "android", + #[cfg(any(linux_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", + #[cfg(any(linux_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())))] + apple_targets))] OFDEL as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] NL0 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] NL1 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] CR0 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] CR1 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] CR2 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] CR3 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "freebsd", target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] TAB0 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] TAB1 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] TAB2 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "freebsd", target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] TAB3 as tcflag_t; - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] XTABS; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] BS0 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] BS1 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] VT0 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] VT1 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] FF0 as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] 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())))] + #[cfg(bsd)] OXTABS; - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(bsd)] 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", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] NLDLY as tcflag_t; // FIXME: Datatype needs to be corrected in libc for mac - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] CRDLY as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "freebsd", target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] TABDLY as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] BSDLY as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] VTDLY as tcflag_t; - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + apple_targets))] FFDLY as tcflag_t; } } @@ -876,13 +611,7 @@ libc_bitflags! { 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())))] + #[cfg(bsd)] CIGNORE; CS5; CS6; @@ -895,54 +624,30 @@ libc_bitflags! { HUPCL; CLOCAL; #[cfg(not(any(target_os = "redox", target_os = "aix")))] - #[cfg_attr(docsrs, doc(cfg(all())))] CRTSCTS; - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] 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())))] + #[cfg(linux_android)] CBAUDEX; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(bsd)] MDMBUF; - #[cfg(any(target_os = "netbsd", target_os = "openbsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(netbsdlike)] CHWFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(any(freebsdlike, netbsdlike))] CCTS_OFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(any(freebsdlike, netbsdlike))] CRTS_IFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(freebsdlike)] CDTR_IFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(freebsdlike)] CDSR_OFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(freebsdlike)] CCAR_OFLOW; // Bitmasks for use with ControlFlags to select specific settings @@ -957,58 +662,35 @@ 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())))] + #[cfg(bsd)] ALTWERASE; IEXTEN; #[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "aix")))] - #[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())))] + #[cfg(bsd)] 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"))] { + if #[cfg(bsd)] { /// Get input baud rate (see /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)). /// @@ -1141,7 +823,6 @@ pub fn cfmakeraw(termios: &mut Termios) { /// /// 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 { @@ -1242,18 +923,3 @@ pub fn tcgetsid<Fd: AsFd>(fd: Fd) -> Result<Pid> { 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/third_party/rust/nix/src/sys/time.rs b/third_party/rust/nix/src/sys/time.rs index a0160e21ff..af436cabd5 100644 --- a/third_party/rust/nix/src/sys/time.rs +++ b/third_party/rust/nix/src/sys/time.rs @@ -2,7 +2,6 @@ // 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}; @@ -18,7 +17,7 @@ const fn zero_init_timespec() -> timespec { all( any( target_os = "freebsd", - target_os = "illumos", + solarish, target_os = "linux", target_os = "netbsd" ), @@ -88,7 +87,7 @@ pub(crate) mod timer { Interval(TimeSpec), } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] bitflags! { /// Flags that are used for arming the timer. #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] @@ -97,12 +96,7 @@ pub(crate) mod timer { const TFD_TIMER_CANCEL_ON_SET = libc::TFD_TIMER_CANCEL_ON_SET; } } - #[cfg(any( - target_os = "freebsd", - target_os = "netbsd", - target_os = "dragonfly", - target_os = "illumos" - ))] + #[cfg(any(freebsdlike, target_os = "netbsd", solarish))] bitflags! { /// Flags that are used for arming the timer. #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] @@ -334,6 +328,17 @@ impl TimeValLike for TimeSpec { } impl TimeSpec { + /// Leave the timestamp unchanged. + #[cfg(not(target_os = "redox"))] + // At the time of writing this PR, redox does not support this feature + pub const UTIME_OMIT: TimeSpec = + TimeSpec::new(0, libc::UTIME_OMIT as timespec_tv_nsec_t); + /// Update the timestamp to `Now` + // At the time of writing this PR, redox does not support this feature + #[cfg(not(target_os = "redox"))] + pub const UTIME_NOW: TimeSpec = + TimeSpec::new(0, libc::UTIME_NOW as timespec_tv_nsec_t); + /// 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 { @@ -712,101 +717,3 @@ fn mod_floor_64(this: i64, other: i64) -> i64 { 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/third_party/rust/nix/src/sys/timerfd.rs b/third_party/rust/nix/src/sys/timerfd.rs index c4337c9dfa..68b06d6322 100644 --- a/third_party/rust/nix/src/sys/timerfd.rs +++ b/third_party/rust/nix/src/sys/timerfd.rs @@ -53,7 +53,7 @@ impl AsFd for TimerFd { impl FromRawFd for TimerFd { unsafe fn from_raw_fd(fd: RawFd) -> Self { TimerFd { - fd: OwnedFd::from_raw_fd(fd), + fd: unsafe { OwnedFd::from_raw_fd(fd) }, } } } diff --git a/third_party/rust/nix/src/sys/uio.rs b/third_party/rust/nix/src/sys/uio.rs index eaf61edfd4..cdf380dd11 100644 --- a/third_party/rust/nix/src/sys/uio.rs +++ b/third_party/rust/nix/src/sys/uio.rs @@ -2,7 +2,7 @@ use crate::errno::Errno; use crate::Result; -use libc::{self, c_int, c_void, off_t, size_t}; +use libc::{self, c_int, off_t, size_t}; use std::io::{IoSlice, IoSliceMut}; use std::os::unix::io::{AsFd, AsRawFd}; @@ -18,7 +18,11 @@ pub fn writev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>]) -> Result<usize> { // // Because it is ABI compatible, a pointer cast here is valid let res = unsafe { - libc::writev(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int) + libc::writev( + fd.as_fd().as_raw_fd(), + iov.as_ptr().cast(), + iov.len() as c_int, + ) }; Errno::result(res).map(|r| r as usize) @@ -33,7 +37,11 @@ pub fn writev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>]) -> Result<usize> { pub fn readv<Fd: AsFd>(fd: Fd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> { // SAFETY: same as in writev(), IoSliceMut is ABI-compatible with iovec let res = unsafe { - libc::readv(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int) + libc::readv( + fd.as_fd().as_raw_fd(), + iov.as_ptr().cast(), + iov.len() as c_int, + ) }; Errno::result(res).map(|r| r as usize) @@ -45,9 +53,12 @@ pub fn readv<Fd: AsFd>(fd: Fd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> { /// 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: AsFd>(fd: Fd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> { +#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "solaris")))] +pub fn pwritev<Fd: AsFd>( + fd: Fd, + iov: &[IoSlice<'_>], + offset: off_t, +) -> Result<usize> { #[cfg(target_env = "uclibc")] let offset = offset as libc::off64_t; // uclibc doesn't use off_t @@ -55,7 +66,7 @@ pub fn pwritev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>], offset: off_t) -> Result<u let res = unsafe { libc::pwritev( fd.as_fd().as_raw_fd(), - iov.as_ptr() as *const libc::iovec, + iov.as_ptr().cast(), iov.len() as c_int, offset, ) @@ -71,8 +82,7 @@ pub fn pwritev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>], offset: off_t) -> Result<u /// 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())))] +#[cfg(not(any(target_os = "redox", target_os = "haiku", target_os = "solaris")))] // Clippy doesn't know that we need to pass iov mutably only because the // mutation happens after converting iov to a pointer #[allow(clippy::needless_pass_by_ref_mut)] @@ -88,7 +98,7 @@ pub fn preadv<Fd: AsFd>( let res = unsafe { libc::preadv( fd.as_fd().as_raw_fd(), - iov.as_ptr() as *const libc::iovec, + iov.as_ptr().cast(), iov.len() as c_int, offset, ) @@ -105,7 +115,7 @@ pub fn pwrite<Fd: AsFd>(fd: Fd, buf: &[u8], offset: off_t) -> Result<usize> { let res = unsafe { libc::pwrite( fd.as_fd().as_raw_fd(), - buf.as_ptr() as *const c_void, + buf.as_ptr().cast(), buf.len() as size_t, offset, ) @@ -122,7 +132,7 @@ pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: off_t) -> Result<usize> { let res = unsafe { libc::pread( fd.as_fd().as_raw_fd(), - buf.as_mut_ptr() as *mut c_void, + buf.as_mut_ptr().cast(), buf.len() as size_t, offset, ) @@ -139,8 +149,7 @@ pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: off_t) -> Result<usize> { /// 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())))] +#[cfg(linux_android)] #[repr(C)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct RemoteIoVec { @@ -173,7 +182,7 @@ feature! { /// [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")))] +#[cfg(all(linux_android, not(target_env = "uclibc")))] pub fn process_vm_writev( pid: crate::unistd::Pid, local_iov: &[IoSlice<'_>], @@ -181,8 +190,8 @@ pub fn process_vm_writev( { 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) + local_iov.as_ptr().cast(), local_iov.len() as libc::c_ulong, + remote_iov.as_ptr().cast(), remote_iov.len() as libc::c_ulong, 0) }; Errno::result(res).map(|r| r as usize) @@ -208,7 +217,7 @@ pub fn process_vm_writev( /// [`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")))] +#[cfg(all(linux_android, not(target_env = "uclibc")))] pub fn process_vm_readv( pid: crate::unistd::Pid, local_iov: &mut [IoSliceMut<'_>], @@ -216,8 +225,8 @@ pub fn process_vm_readv( { 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) + local_iov.as_ptr().cast(), local_iov.len() as libc::c_ulong, + remote_iov.as_ptr().cast(), remote_iov.len() as libc::c_ulong, 0) }; Errno::result(res).map(|r| r as usize) diff --git a/third_party/rust/nix/src/sys/utsname.rs b/third_party/rust/nix/src/sys/utsname.rs index b48ed9f45e..cf4e6cc738 100644 --- a/third_party/rust/nix/src/sys/utsname.rs +++ b/third_party/rust/nix/src/sys/utsname.rs @@ -37,7 +37,7 @@ impl UtsName { } /// NIS or YP domain name of this machine. - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] pub fn domainname(&self) -> &OsStr { cast_and_trim(&self.0.domainname) } @@ -62,24 +62,3 @@ fn cast_and_trim(slice: &[c_char]) -> &OsStr { 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/third_party/rust/nix/src/sys/wait.rs b/third_party/rust/nix/src/sys/wait.rs index f7a63ffcd2..844e165c18 100644 --- a/third_party/rust/nix/src/sys/wait.rs +++ b/third_party/rust/nix/src/sys/wait.rs @@ -24,53 +24,41 @@ libc_bitflags!( /// [`SIGSTOP`](crate::sys::signal::Signal::SIGSTOP) signal. WUNTRACED; /// Report the status of selected processes which have terminated. - #[cfg(any(target_os = "android", + #[cfg(any(linux_android, + apple_targets, 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", + #[cfg(any(linux_android, + apple_targets, 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", + #[cfg(any(linux_android, + apple_targets, 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())))] + #[cfg(any(linux_android, target_os = "redox"))] __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())))] + #[cfg(any(linux_android, target_os = "redox"))] __WALL; /// Wait for "clone" children only. - #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(any(linux_android, target_os = "redox"))] __WCLONE; } ); @@ -107,16 +95,14 @@ pub enum WaitStatus { /// /// [`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())))] + #[cfg(linux_android)] PtraceEvent(Pid, Signal, c_int), /// The traced process was stopped by execution of a system call, /// and `PTRACE_O_TRACESYSGOOD` is in effect. See [`ptrace`(2)] for /// more information. /// /// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html - #[cfg(any(target_os = "linux", target_os = "android"))] - #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(linux_android)] PtraceSyscall(Pid), /// The process was previously stopped but has resumed execution /// after receiving a `SIGCONT` signal. This is only reported if @@ -139,7 +125,7 @@ impl WaitStatus { Some(p) } StillAlive => None, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p), } } @@ -173,7 +159,7 @@ fn stop_signal(status: i32) -> Result<Signal> { Signal::try_from(libc::WSTOPSIG(status)) } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] 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 @@ -182,7 +168,7 @@ fn syscall_stop(status: i32) -> bool { libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_android)] fn stop_additional(status: i32) -> c_int { (status >> 16) as c_int } @@ -216,7 +202,7 @@ impl WaitStatus { WaitStatus::Signaled(pid, term_signal(status)?, dumped_core(status)) } else if stopped(status) { cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { + if #[cfg(linux_android)] { fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> { let status_additional = stop_additional(status); Ok(if syscall_stop(status) { @@ -259,7 +245,7 @@ impl WaitStatus { all(target_os = "linux", not(target_env = "uclibc")), ))] unsafe fn from_siginfo(siginfo: &libc::siginfo_t) -> Result<WaitStatus> { - let si_pid = siginfo.si_pid(); + let si_pid = unsafe { siginfo.si_pid() }; if si_pid == 0 { return Ok(WaitStatus::StillAlive); } @@ -267,7 +253,7 @@ impl WaitStatus { assert_eq!(siginfo.si_signo, libc::SIGCHLD); let pid = Pid::from_raw(si_pid); - let si_status = siginfo.si_status(); + let si_status = unsafe { siginfo.si_status() }; let status = match siginfo.si_code { libc::CLD_EXITED => WaitStatus::Exited(pid, si_status), @@ -280,7 +266,7 @@ impl WaitStatus { WaitStatus::Stopped(pid, Signal::try_from(si_status)?) } libc::CLD_CONTINUED => WaitStatus::Continued(pid), - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_android)] libc::CLD_TRAPPED => { if si_status == libc::SIGTRAP | 0x80 { WaitStatus::PtraceSyscall(pid) @@ -354,7 +340,7 @@ pub enum Id<'fd> { /// 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"))] + #[cfg(linux_android)] PIDFd(BorrowedFd<'fd>), /// A helper variant to resolve the unused parameter (`'fd`) problem on platforms /// other than Linux and Android. @@ -376,9 +362,11 @@ pub fn waitid(id: Id, flags: WaitPidFlag) -> Result<WaitStatus> { 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"))] + #[cfg(linux_android)] Id::PIDFd(fd) => (libc::P_PIDFD, fd.as_raw_fd() as libc::id_t), - Id::_Unreachable(_) => unreachable!("This variant could never be constructed"), + Id::_Unreachable(_) => { + unreachable!("This variant could never be constructed") + } }; let siginfo = unsafe { |