From 2075ac70bdd4848b08213a237feb32f5506096e0 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 10 Mar 2019 08:23:52 -0700 Subject: [PATCH 1/6] Enable libc extra_traits feature Also bump Rust requirement to 1.25 which is a requirement of that feature --- .cirrus.yml | 2 +- .travis.yml | 50 +++++++++++++++++++++++++------------------------- CHANGELOG.md | 2 ++ Cargo.toml | 2 +- README.md | 5 +++-- 5 files changed, 32 insertions(+), 29 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 00d0095c23..eca3d347c4 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -14,7 +14,7 @@ task: setup_script: - pkg install -y curl - curl https://sh.rustup.rs -sSf --output rustup.sh - - sh rustup.sh -y --default-toolchain 1.24.1 + - sh rustup.sh -y --default-toolchain 1.25.0 - $HOME/.cargo/bin/rustup target add i686-unknown-freebsd amd64_test_script: - . $HOME/.cargo/env diff --git a/.travis.yml b/.travis.yml index bd14c30eb8..cb7e10247a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,71 +18,71 @@ matrix: # week. Additionally they're moved to the front of the line to get them in # the Travis OS X build queue first. - env: TARGET="aarch64-apple-ios;armv7-apple-ios;armv7s-apple-ios;i386-apple-ios;x86_64-apple-ios" DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 os: osx # Mac builds # These are also moved to be first because they wait in a long queue with # Travis - env: TARGET=i686-apple-darwin - rust: 1.24.1 + rust: 1.25.0 os: osx - env: TARGET=x86_64-apple-darwin - rust: 1.24.1 + rust: 1.25.0 os: osx # Android - env: TARGET=aarch64-linux-android DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=arm-linux-androideabi DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=armv7-linux-androideabi DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=i686-linux-android DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=x86_64-linux-android DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 # Linux - env: TARGET=aarch64-unknown-linux-gnu - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=arm-unknown-linux-gnueabi - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=arm-unknown-linux-musleabi DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=armv7-unknown-linux-gnueabihf - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=i686-unknown-linux-gnu - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=i686-unknown-linux-musl - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=mips-unknown-linux-gnu - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=mips64-unknown-linux-gnuabi64 - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=mips64el-unknown-linux-gnuabi64 - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=mipsel-unknown-linux-gnu - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=powerpc-unknown-linux-gnu DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=powerpc64-unknown-linux-gnu - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=powerpc64le-unknown-linux-gnu - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=s390x-unknown-linux-gnu DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=x86_64-unknown-linux-gnu - rust: 1.24.1 + rust: 1.25.0 - env: TARGET=x86_64-unknown-linux-musl - rust: 1.24.1 + rust: 1.25.0 # *BSD # FreeBSD i686 and x86_64 use Cirrus instead of Travis # - env: TARGET=i686-unknown-freebsd DISABLE_TESTS=1 # - env: TARGET=x86_64-unknown-freebsd DISABLE_TESTS=1 - env: TARGET=x86_64-unknown-netbsd DISABLE_TESTS=1 - rust: 1.24.1 + rust: 1.25.0 # Make sure stable is always working too - env: TARGET=x86_64-unknown-linux-gnu diff --git a/CHANGELOG.md b/CHANGELOG.md index 3420681b3a..712a799e1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). native equivalents like `u32.` ([#1072](https://github.com/nix-rust/nix/pull/1072/commits)) +- Minimum supported Rust version is now 1.25.0 + ([#1035](https://github.com/nix-rust/nix/pull/1035)) ### Fixed - Fix the build on Android and Linux/mips with recent versions of libc. ([#1072](https://github.com/nix-rust/nix/pull/1072/commits)) diff --git a/Cargo.toml b/Cargo.toml index 3032606265..622e4331c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ exclude = [ ] [dependencies] -libc = { git = "https://github.com/rust-lang/libc" } +libc = { git = "https://github.com/rust-lang/libc", features = [ "extra_traits" ] } bitflags = "1.0" cfg-if = "0.1.0" void = "1.0.2" diff --git a/README.md b/README.md index 23a20532ee..41ee98a525 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,7 @@ limitations. Support for platforms is split into three tiers: *do not* block the inclusion of new code. Testing may be run, but failures in tests don't block the inclusion of new code. -The following targets are all supported by nix on Rust 1.24.1 or newer (unless -otherwise noted): +The following targets are supported by `nix`: Tier 1: * aarch64-unknown-linux-gnu @@ -84,6 +83,8 @@ Tier 2: ## Usage +`nix` requires Rust 1.25.0 or newer. + To use `nix`, first add this to your `Cargo.toml`: ```toml From c50e987b4e169e2d7dc7089c91407e1e55c550f1 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 10 Mar 2019 08:29:23 -0700 Subject: [PATCH 2/6] Add extra traits for all types Derive Clone, Copy, Eq, Hash, and PartialEq for all types. Not all traits are supported by all types, which is why many are missing some. --- CHANGELOG.md | 6 +- src/dir.rs | 27 +-- src/fcntl.rs | 5 +- src/ifaddrs.rs | 2 +- src/lib.rs | 2 +- src/mqueue.rs | 13 +- src/poll.rs | 20 +-- src/pty.rs | 5 +- src/sched.rs | 3 +- src/sys/aio.rs | 10 +- src/sys/epoll.rs | 3 +- src/sys/event.rs | 3 +- src/sys/quota.rs | 3 +- src/sys/select.rs | 3 +- src/sys/sendfile.rs | 2 +- src/sys/signal.rs | 38 +--- src/sys/socket/addr.rs | 364 +++----------------------------------- src/sys/socket/mod.rs | 75 ++------ src/sys/socket/sockopt.rs | 6 +- src/sys/statvfs.rs | 3 +- src/sys/sysinfo.rs | 3 +- src/sys/termios.rs | 3 +- src/sys/time.rs | 42 +---- src/sys/uio.rs | 5 +- src/sys/utsname.rs | 3 +- src/sys/wait.rs | 2 +- src/ucontext.rs | 3 +- test/sys/test_socket.rs | 37 +++- 28 files changed, 116 insertions(+), 575 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 712a799e1f..61c0cc80cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,14 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added - Added `MSG_WAITALL` to `MsgFlags` in `sys::socket`. ([#1079](https://github.com/nix-rust/nix/pull/1079)) +- Implemented `Clone`, `Copy`, `Debug`, `Eq`, `Hash`, and `PartialEq` for most + types that support them. ([#1035](https://github.com/nix-rust/nix/pull/1035)) ### Changed - Support for `ifaddrs` now present when building for Android. ([#1077](https://github.com/nix-rust/nix/pull/1077)) +- Minimum supported Rust version is now 1.25.0 + ([#1035](https://github.com/nix-rust/nix/pull/1035)) ### Fixed ### Removed @@ -35,8 +39,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). native equivalents like `u32.` ([#1072](https://github.com/nix-rust/nix/pull/1072/commits)) -- Minimum supported Rust version is now 1.25.0 - ([#1035](https://github.com/nix-rust/nix/pull/1035)) ### Fixed - Fix the build on Android and Linux/mips with recent versions of libc. ([#1072](https://github.com/nix-rust/nix/pull/1072/commits)) diff --git a/src/dir.rs b/src/dir.rs index 814e9e0c0b..d4fc43a4d0 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -3,7 +3,7 @@ use errno::Errno; use fcntl::{self, OFlag}; use libc; use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd}; -use std::{ffi, fmt, ptr}; +use std::{ffi, ptr}; use sys; #[cfg(target_os = "linux")] @@ -25,6 +25,7 @@ use libc::{dirent, readdir_r}; /// * returns entries for `.` (current directory) and `..` (parent directory). /// * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc /// does). +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Dir( // This could be ptr::NonNull once nix requires Rust 1.25. *mut libc::DIR @@ -82,21 +83,13 @@ impl AsRawFd for Dir { } } -impl fmt::Debug for Dir { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Dir") - .field("fd", &self.as_raw_fd()) - .finish() - } -} - impl Drop for Dir { fn drop(&mut self) { unsafe { libc::closedir(self.0) }; } } -#[derive(Debug)] +#[derive(Debug, Eq, Hash, PartialEq)] pub struct Iter<'d>(&'d mut Dir); impl<'d> Iterator for Iter<'d> { @@ -132,10 +125,10 @@ impl<'d> Drop for Iter<'d> { /// A directory entry, similar to `std::fs::DirEntry`. /// /// Note that unlike the std version, this may represent the `.` or `..` entries. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] pub struct Entry(dirent); -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] pub enum Type { Fifo, CharacterDevice, @@ -198,13 +191,3 @@ impl Entry { } } } - -impl fmt::Debug for Entry { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Entry") - .field("ino", &self.ino()) - .field("file_name", &self.file_name()) - .field("file_type", &self.file_type()) - .finish() - } -} diff --git a/src/fcntl.rs b/src/fcntl.rs index 40f4cf9405..6da62d87ba 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -214,7 +214,7 @@ libc_bitflags!( } ); -#[allow(missing_debug_implementations)] +#[derive(Debug, Eq, Hash, PartialEq)] pub enum FcntlArg<'a> { F_DUPFD(RawFd), F_DUPFD_CLOEXEC(RawFd), @@ -277,8 +277,7 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result { Errno::result(res) } -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum FlockArg { LockShared, LockExclusive, diff --git a/src/ifaddrs.rs b/src/ifaddrs.rs index c979077392..12b59bcc92 100644 --- a/src/ifaddrs.rs +++ b/src/ifaddrs.rs @@ -15,7 +15,7 @@ use sys::socket::SockAddr; use net::if_::*; /// Describes a single address for an interface as returned by `getifaddrs`. -#[derive(Clone, Eq, Hash, PartialEq, Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct InterfaceAddress { /// Name of the network interface pub interface_name: String, diff --git a/src/lib.rs b/src/lib.rs index 7ef91f4e8d..b46489331e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,7 +98,7 @@ pub type Result = result::Result; /// error has a corresponding errno (usually the one from the /// underlying OS) to which it can be mapped in addition to /// implementing other common traits. -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Error { Sys(Errno), InvalidPath, diff --git a/src/mqueue.rs b/src/mqueue.rs index 87be65321b..b958b71cdd 100644 --- a/src/mqueue.rs +++ b/src/mqueue.rs @@ -29,22 +29,11 @@ libc_bitflags!{ } #[repr(C)] -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct MqAttr { mq_attr: libc::mq_attr, } -impl PartialEq for MqAttr { - fn eq(&self, other: &MqAttr) -> bool { - let self_attr = self.mq_attr; - let other_attr = other.mq_attr; - self_attr.mq_flags == other_attr.mq_flags && self_attr.mq_maxmsg == other_attr.mq_maxmsg && - self_attr.mq_msgsize == other_attr.mq_msgsize && - self_attr.mq_curmsgs == other_attr.mq_curmsgs - } -} - impl MqAttr { pub fn new(mq_flags: c_long, mq_maxmsg: c_long, diff --git a/src/poll.rs b/src/poll.rs index 160b5bc605..c603611e31 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -4,7 +4,6 @@ use sys::time::TimeSpec; #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] use sys::signal::SigSet; use std::os::unix::io::RawFd; -use std::fmt; use libc; use Result; @@ -19,7 +18,7 @@ use errno::Errno; /// After a call to `poll` or `ppoll`, the events that occured can be /// retrieved by calling [`revents()`](#method.revents) on the `PollFd`. #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct PollFd { pollfd: libc::pollfd, } @@ -43,23 +42,6 @@ impl PollFd { } } -impl fmt::Debug for PollFd { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let pfd = self.pollfd; - let mut ds = f.debug_struct("PollFd"); - ds.field("fd", &pfd.fd); - match PollFlags::from_bits(pfd.events) { - None => ds.field("events", &pfd.events), - Some(ef) => ds.field("events", &ef), - }; - match PollFlags::from_bits(pfd.revents) { - None => ds.field("revents", &pfd.revents), - Some(ef) => ds.field("revents", &ef), - }; - ds.finish() - } -} - libc_bitflags! { /// These flags define the different events that can be monitored by `poll` and `ppoll` pub struct PollFlags: libc::c_short { diff --git a/src/pty.rs b/src/pty.rs index 41bd51b68a..db012d8158 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -18,8 +18,7 @@ use errno::Errno; /// /// This is returned by `openpty`. Note that this type does *not* implement `Drop`, so the user /// must manually close the file descriptors. -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct OpenptyResult { /// The master port in a virtual pty pair pub master: RawFd, @@ -45,7 +44,7 @@ pub struct ForkptyResult { /// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY /// functions are given the correct file descriptor. Additionally this type implements `Drop`, /// so that when it's consumed or goes out of scope, it's automatically cleaned-up. -#[derive(Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct PtyMaster(RawFd); impl AsRawFd for PtyMaster { diff --git a/src/sched.rs b/src/sched.rs index d381cbb5bb..c4e6ca7a1a 100644 --- a/src/sched.rs +++ b/src/sched.rs @@ -39,8 +39,7 @@ libc_bitflags!{ pub type CloneCb<'a> = Box isize + 'a>; #[repr(C)] -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct CpuSet { cpu_set: libc::cpu_set_t, } diff --git a/src/sys/aio.rs b/src/sys/aio.rs index c54c2e316e..40fa4e1517 100644 --- a/src/sys/aio.rs +++ b/src/sys/aio.rs @@ -80,7 +80,7 @@ libc_enum! { /// Return values for [`AioCb::cancel`](struct.AioCb.html#method.cancel) and /// [`aio_cancel_all`](fn.aio_cancel_all.html) #[repr(i32)] -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum AioCancelStat { /// All outstanding requests were canceled AioCanceled = libc::AIO_CANCELED, @@ -1021,13 +1021,7 @@ pub fn aio_suspend(list: &[&AioCb], timeout: Option) -> Result<()> { impl<'a> Debug for AioCb<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("AioCb") - .field("aio_fildes", &self.aiocb.aio_fildes) - .field("aio_offset", &self.aiocb.aio_offset) - .field("aio_buf", &self.aiocb.aio_buf) - .field("aio_nbytes", &self.aiocb.aio_nbytes) - .field("aio_lio_opcode", &self.aiocb.aio_lio_opcode) - .field("aio_reqprio", &self.aiocb.aio_reqprio) - .field("aio_sigevent", &SigEvent::from(&self.aiocb.aio_sigevent)) + .field("aiocb", &self.aiocb) .field("mutable", &self.mutable) .field("in_progress", &self.in_progress) .finish() diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs index 3ed1dd7240..fef6f4e3ec 100644 --- a/src/sys/epoll.rs +++ b/src/sys/epoll.rs @@ -42,8 +42,7 @@ libc_bitflags!{ } } -#[allow(missing_debug_implementations)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[repr(C)] pub struct EpollEvent { event: libc::epoll_event, diff --git a/src/sys/event.rs b/src/sys/event.rs index f1eaa0d155..8cd7372f88 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -12,9 +12,8 @@ use std::ptr; use std::mem; // Redefine kevent in terms of programmer-friendly enums and bitfields. -#[derive(Clone, Copy)] #[repr(C)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct KEvent { kevent: libc::kevent, } diff --git a/src/sys/quota.rs b/src/sys/quota.rs index 14c0462929..8946fca221 100644 --- a/src/sys/quota.rs +++ b/src/sys/quota.rs @@ -96,8 +96,7 @@ libc_bitflags!( /// Wrapper type for `if_dqblk` // FIXME: Change to repr(transparent) #[repr(C)] -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct Dqblk(libc::dqblk); impl Default for Dqblk { diff --git a/src/sys/select.rs b/src/sys/select.rs index 95b6b148f6..1b518e29f6 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -11,8 +11,7 @@ pub use libc::FD_SETSIZE; // FIXME: Change to repr(transparent) once it's stable #[repr(C)] -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct FdSet(libc::fd_set); impl FdSet { diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs index 1190518d8b..a47d8962f7 100644 --- a/src/sys/sendfile.rs +++ b/src/sys/sendfile.rs @@ -38,7 +38,7 @@ cfg_if! { target_os = "macos"))] { use sys::uio::IoVec; - #[allow(missing_debug_implementations)] + #[derive(Clone, Debug, Eq, Hash, PartialEq)] struct SendfileHeaderTrailer<'a>( libc::sf_hdtr, Option>>, diff --git a/src/sys/signal.rs b/src/sys/signal.rs index a49b273f8a..1013a77fd4 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -265,8 +265,7 @@ const SIGNALS: [Signal; 31] = [ pub const NSIG: libc::c_int = 32; -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct SignalIterator { next: usize, } @@ -328,8 +327,7 @@ libc_enum! { } } -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct SigSet { sigset: libc::sigset_t } @@ -427,7 +425,7 @@ impl AsRef for SigSet { /// A signal handler. #[allow(unknown_lints)] -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum SigHandler { /// Default signal handling. SigDfl, @@ -441,8 +439,7 @@ pub enum SigHandler { } /// Action to take on receipt of a signal. Corresponds to `sigaction`. -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct SigAction { sigaction: libc::sigaction } @@ -683,7 +680,7 @@ pub type type_of_thread_id = libc::pid_t; // 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. -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum SigevNotify { /// No notification will be delivered SigevNone, @@ -710,7 +707,6 @@ mod sigevent { use libc; use std::mem; use std::ptr; - use std::fmt::{self, Debug}; use super::SigevNotify; #[cfg(any(target_os = "freebsd", target_os = "linux"))] use super::type_of_thread_id; @@ -718,7 +714,7 @@ mod sigevent { /// Used to request asynchronous notification of the completion of certain /// events, such as POSIX AIO and timers. #[repr(C)] - #[derive(Clone, Copy)] + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct SigEvent { sigevent: libc::sigevent } @@ -788,28 +784,6 @@ mod sigevent { } } - impl Debug for SigEvent { - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("SigEvent") - .field("sigev_notify", &self.sigevent.sigev_notify) - .field("sigev_signo", &self.sigevent.sigev_signo) - .field("sigev_value", &self.sigevent.sigev_value.sival_ptr) - .field("sigev_notify_thread_id", - &self.sigevent.sigev_notify_thread_id) - .finish() - } - - #[cfg(not(any(target_os = "freebsd", target_os = "linux")))] - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("SigEvent") - .field("sigev_notify", &self.sigevent.sigev_notify) - .field("sigev_signo", &self.sigevent.sigev_signo) - .field("sigev_value", &self.sigevent.sigev_value.sival_ptr) - .finish() - } - } - impl<'a> From<&'a libc::sigevent> for SigEvent { fn from(sigevent: &libc::sigevent) -> Self { SigEvent{ sigevent: *sigevent } diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index fc24bd792b..c698822761 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -2,8 +2,9 @@ use super::sa_family_t; use {Error, Result, NixPath}; use errno::Errno; use libc; -use std::{fmt, hash, mem, net, ptr, slice}; +use std::{fmt, mem, net, ptr, slice}; use std::ffi::OsStr; +use std::hash::{Hash, Hasher}; use std::path::Path; use std::os::unix::ffi::OsStrExt; #[cfg(any(target_os = "android", target_os = "linux"))] @@ -245,7 +246,7 @@ impl AddressFamily { } } -#[derive(Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum InetAddr { V4(libc::sockaddr_in), V6(libc::sockaddr_in6), @@ -331,52 +332,6 @@ impl InetAddr { } } -impl PartialEq for InetAddr { - fn eq(&self, other: &InetAddr) -> bool { - match (*self, *other) { - (InetAddr::V4(ref a), InetAddr::V4(ref b)) => { - a.sin_port == b.sin_port && - a.sin_addr.s_addr == b.sin_addr.s_addr - } - (InetAddr::V6(ref a), InetAddr::V6(ref b)) => { - a.sin6_port == b.sin6_port && - a.sin6_addr.s6_addr == b.sin6_addr.s6_addr && - a.sin6_flowinfo == b.sin6_flowinfo && - a.sin6_scope_id == b.sin6_scope_id - } - _ => false, - } - } -} - -impl Eq for InetAddr { -} - -impl hash::Hash for InetAddr { - fn hash(&self, s: &mut H) { - match *self { - InetAddr::V4(ref a) => { - ( a.sin_family, - a.sin_port, - a.sin_addr.s_addr ).hash(s) - } - InetAddr::V6(ref a) => { - ( a.sin6_family, - a.sin6_port, - &a.sin6_addr.s6_addr, - a.sin6_flowinfo, - a.sin6_scope_id ).hash(s) - } - } - } -} - -impl Clone for InetAddr { - fn clone(&self) -> InetAddr { - *self - } -} - impl fmt::Display for InetAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -386,18 +341,12 @@ impl fmt::Display for InetAddr { } } -impl fmt::Debug for InetAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - /* * * ===== IpAddr ===== * */ -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), @@ -442,19 +391,13 @@ impl fmt::Display for IpAddr { } } -impl fmt::Debug for IpAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - /* * * ===== Ipv4Addr ===== * */ -#[derive(Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct Ipv4Addr(pub libc::in_addr); impl Ipv4Addr { @@ -487,28 +430,6 @@ impl Ipv4Addr { } } -impl PartialEq for Ipv4Addr { - fn eq(&self, other: &Ipv4Addr) -> bool { - self.0.s_addr == other.0.s_addr - } -} - -impl Eq for Ipv4Addr { -} - -impl hash::Hash for Ipv4Addr { - fn hash(&self, s: &mut H) { - let saddr = self.0.s_addr; - saddr.hash(s) - } -} - -impl Clone for Ipv4Addr { - fn clone(&self) -> Ipv4Addr { - *self - } -} - impl fmt::Display for Ipv4Addr { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let octets = self.octets(); @@ -516,19 +437,13 @@ impl fmt::Display for Ipv4Addr { } } -impl fmt::Debug for Ipv4Addr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - /* * * ===== Ipv6Addr ===== * */ -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct Ipv6Addr(pub libc::in6_addr); // Note that IPv6 addresses are stored in big endian order on all architectures. @@ -576,18 +491,6 @@ impl fmt::Display for Ipv6Addr { } } -impl fmt::Debug for Ipv6Addr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -/* - * - * ===== UnixAddr ===== - * - */ - /// A wrapper around `sockaddr_un`. /// /// This also tracks the length of `sun_path` address (excluding @@ -596,7 +499,7 @@ impl fmt::Debug for Ipv6Addr { /// does not require that `sun_len` include the terminating null even for normal /// sockets. Note that the actual sockaddr length is greater by /// `offset_of!(libc::sockaddr_un, sun_path)` -#[derive(Copy)] +#[derive(Clone, Copy, Debug)] pub struct UnixAddr(pub libc::sockaddr_un, pub usize); impl UnixAddr { @@ -688,27 +591,6 @@ impl UnixAddr { } } -impl PartialEq for UnixAddr { - fn eq(&self, other: &UnixAddr) -> bool { - self.sun_path() == other.sun_path() - } -} - -impl Eq for UnixAddr { -} - -impl hash::Hash for UnixAddr { - fn hash(&self, s: &mut H) { - ( self.0.sun_family, self.sun_path() ).hash(s) - } -} - -impl Clone for UnixAddr { - fn clone(&self) -> UnixAddr { - *self - } -} - impl fmt::Display for UnixAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.1 == 0 { @@ -722,20 +604,22 @@ impl fmt::Display for UnixAddr { } } -impl fmt::Debug for UnixAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) +impl PartialEq for UnixAddr { + fn eq(&self, other: &UnixAddr) -> bool { + self.sun_path() == other.sun_path() } } -/* - * - * ===== Sock addr ===== - * - */ +impl Eq for UnixAddr {} + +impl Hash for UnixAddr { + fn hash(&self, s: &mut H) { + ( self.0.sun_family, self.sun_path() ).hash(s) + } +} /// Represents a socket address -#[derive(Copy, Debug)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum SockAddr { Inet(InetAddr), Unix(UnixAddr), @@ -883,68 +767,6 @@ impl SockAddr { } } -impl PartialEq for SockAddr { - fn eq(&self, other: &SockAddr) -> bool { - match (*self, *other) { - (SockAddr::Inet(ref a), SockAddr::Inet(ref b)) => { - a == b - } - (SockAddr::Unix(ref a), SockAddr::Unix(ref b)) => { - a == b - } - #[cfg(any(target_os = "android", target_os = "linux"))] - (SockAddr::Netlink(ref a), SockAddr::Netlink(ref b)) => { - a == b - } - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - (SockAddr::Link(ref a), SockAddr::Link(ref b)) => { - a == b - } - _ => false, - } - } -} - -impl Eq for SockAddr { -} - -impl hash::Hash for SockAddr { - fn hash(&self, s: &mut H) { - match *self { - SockAddr::Inet(ref a) => a.hash(s), - SockAddr::Unix(ref a) => a.hash(s), - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Netlink(ref a) => a.hash(s), - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Alg(ref a) => a.hash(s), - #[cfg(any(target_os = "ios", target_os = "macos"))] - SockAddr::SysControl(ref a) => a.hash(s), - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - SockAddr::Link(ref ether_addr) => ether_addr.hash(s) - } - } -} - -impl Clone for SockAddr { - fn clone(&self) -> SockAddr { - *self - } -} - impl fmt::Display for SockAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -974,30 +796,10 @@ pub mod netlink { use ::sys::socket::addr::AddressFamily; use libc::{sa_family_t, sockaddr_nl}; use std::{fmt, mem}; - use std::hash::{Hash, Hasher}; - #[derive(Copy, Clone)] + #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] pub struct NetlinkAddr(pub sockaddr_nl); - // , PartialEq, Eq, Debug, Hash - impl PartialEq for NetlinkAddr { - fn eq(&self, other: &Self) -> bool { - let (inner, other) = (self.0, other.0); - (inner.nl_family, inner.nl_pid, inner.nl_groups) == - (other.nl_family, other.nl_pid, other.nl_groups) - } - } - - impl Eq for NetlinkAddr {} - - impl Hash for NetlinkAddr { - fn hash(&self, s: &mut H) { - let inner = self.0; - (inner.nl_family, inner.nl_pid, inner.nl_groups).hash(s); - } - } - - impl NetlinkAddr { pub fn new(pid: u32, groups: u32) -> NetlinkAddr { let mut addr: sockaddr_nl = unsafe { mem::zeroed() }; @@ -1022,12 +824,6 @@ pub mod netlink { write!(f, "pid: {} groups: {}", self.pid(), self.groups()) } } - - impl fmt::Debug for NetlinkAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } - } } #[cfg(any(target_os = "android", target_os = "linux"))] @@ -1098,11 +894,13 @@ pub mod sys_control { use ::sys::socket::addr::AddressFamily; use libc::{self, c_uchar}; use std::{fmt, mem}; - use std::hash::{Hash, Hasher}; use std::os::unix::io::RawFd; use {Errno, Error, Result}; + // FIXME: Move type into `libc` #[repr(C)] + #[derive(Clone, Copy)] + #[allow(missing_debug_implementations)] pub struct ctl_ioc_info { pub ctl_id: u32, pub ctl_name: [c_uchar; MAX_KCTL_NAME], @@ -1114,28 +912,10 @@ pub mod sys_control { ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info); - #[derive(Copy, Clone)] #[repr(C)] + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct SysControlAddr(pub libc::sockaddr_ctl); - impl PartialEq for SysControlAddr { - fn eq(&self, other: &Self) -> bool { - let (inner, other) = (self.0, other.0); - (inner.sc_id, inner.sc_unit) == - (other.sc_id, other.sc_unit) - } - } - - impl Eq for SysControlAddr {} - - impl Hash for SysControlAddr { - fn hash(&self, s: &mut H) { - let inner = self.0; - (inner.sc_id, inner.sc_unit).hash(s); - } - } - - impl SysControlAddr { pub fn new(id: u32, unit: u32) -> SysControlAddr { let addr = libc::sockaddr_ctl { @@ -1178,27 +958,15 @@ pub mod sys_control { fmt::Debug::fmt(self, f) } } - - impl fmt::Debug for SysControlAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("SysControlAddr") - .field("sc_len", &self.0.sc_len) - .field("sc_family", &self.0.sc_family) - .field("ss_sysaddr", &self.0.ss_sysaddr) - .field("sc_id", &self.0.sc_id) - .field("sc_unit", &self.0.sc_unit) - .finish() - } - } } #[cfg(any(target_os = "android", target_os = "linux"))] mod datalink { - use super::{libc, hash, fmt, AddressFamily}; + use super::{libc, fmt, AddressFamily}; /// Hardware Address - #[derive(Clone, Copy)] + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct LinkAddr(pub libc::sockaddr_ll); impl LinkAddr { @@ -1246,26 +1014,6 @@ mod datalink { } } - impl Eq for LinkAddr {} - - impl PartialEq for LinkAddr { - fn eq(&self, other: &Self) -> bool { - let (a, b) = (self.0, other.0); - (a.sll_family, a.sll_protocol, a.sll_ifindex, a.sll_hatype, - a.sll_pkttype, a.sll_halen, a.sll_addr) == - (b.sll_family, b.sll_protocol, b.sll_ifindex, b.sll_hatype, - b.sll_pkttype, b.sll_halen, b.sll_addr) - } - } - - impl hash::Hash for LinkAddr { - fn hash(&self, s: &mut H) { - let a = self.0; - (a.sll_family, a.sll_protocol, a.sll_ifindex, a.sll_hatype, - a.sll_pkttype, a.sll_halen, a.sll_addr).hash(s); - } - } - impl fmt::Display for LinkAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let addr = self.addr(); @@ -1278,12 +1026,6 @@ mod datalink { addr[5]) } } - - impl fmt::Debug for LinkAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } - } } #[cfg(any(target_os = "dragonfly", @@ -1293,10 +1035,10 @@ mod datalink { target_os = "netbsd", target_os = "openbsd"))] mod datalink { - use super::{libc, hash, fmt, AddressFamily}; + use super::{libc, fmt, AddressFamily}; /// Hardware Address - #[derive(Clone, Copy)] + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct LinkAddr(pub libc::sockaddr_dl); impl LinkAddr { @@ -1368,52 +1110,6 @@ mod datalink { } } - impl Eq for LinkAddr {} - - impl PartialEq for LinkAddr { - #[cfg(any(target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - fn eq(&self, other: &Self) -> bool { - let (a, b) = (self.0, other.0); - (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, - a.sdl_nlen, a.sdl_alen, a.sdl_slen, &a.sdl_data[..]) == - (b.sdl_len, b.sdl_family, b.sdl_index, b.sdl_type, - b.sdl_nlen, b.sdl_alen, b.sdl_slen, &b.sdl_data[..]) - } - - #[cfg(target_os = "dragonfly")] - fn eq(&self, other: &Self) -> bool { - let (a, b) = (self.0, other.0); - (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, a.sdl_nlen, - a.sdl_alen, a.sdl_slen, a.sdl_data, a.sdl_rcf, a.sdl_route) == - (b.sdl_len, b.sdl_family, b.sdl_index, b.sdl_type, b.sdl_nlen, - b.sdl_alen, b.sdl_slen, b.sdl_data, b.sdl_rcf, b.sdl_route) - } - } - - impl hash::Hash for LinkAddr { - #[cfg(any(target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - fn hash(&self, s: &mut H) { - let a = self.0; - (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, - a.sdl_nlen, a.sdl_alen, a.sdl_slen, &a.sdl_data[..]).hash(s); - } - - #[cfg(target_os = "dragonfly")] - fn hash(&self, s: &mut H) { - let a = self.0; - (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, a.sdl_nlen, - a.sdl_alen, a.sdl_slen, a.sdl_data, a.sdl_rcf, a.sdl_route).hash(s); - } - } - impl fmt::Display for LinkAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let addr = self.addr(); @@ -1426,12 +1122,6 @@ mod datalink { addr[5]) } } - - impl fmt::Debug for LinkAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } - } } #[cfg(test)] diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index a8631f2461..0e27216fbb 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -5,7 +5,7 @@ use {Error, Result}; use errno::Errno; use libc::{self, c_void, c_int, iovec, socklen_t, size_t, CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN}; -use std::{fmt, mem, ptr, slice}; +use std::{mem, ptr, slice}; use std::os::unix::io::RawFd; use sys::time::TimeVal; use sys::uio::IoVec; @@ -189,7 +189,7 @@ cfg_if! { /// /// This struct is used with the `SO_PEERCRED` ancillary message for UNIX sockets. #[repr(C)] - #[derive(Clone, Copy)] + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct UnixCredentials(libc::ucred); impl UnixCredentials { @@ -209,13 +209,6 @@ cfg_if! { } } - impl PartialEq for UnixCredentials { - fn eq(&self, other: &Self) -> bool { - self.0.pid == other.0.pid && self.0.uid == other.0.uid && self.0.gid == other.0.gid - } - } - impl Eq for UnixCredentials {} - impl From for UnixCredentials { fn from(cred: libc::ucred) -> Self { UnixCredentials(cred) @@ -227,16 +220,6 @@ cfg_if! { self.0 } } - - impl fmt::Debug for UnixCredentials { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("UnixCredentials") - .field("pid", &self.0.pid) - .field("uid", &self.0.uid) - .field("gid", &self.0.gid) - .finish() - } - } } } @@ -244,7 +227,7 @@ cfg_if! { /// /// This is a wrapper type around `ip_mreq`. #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct IpMembershipRequest(libc::ip_mreq); impl IpMembershipRequest { @@ -259,32 +242,11 @@ impl IpMembershipRequest { } } -impl PartialEq for IpMembershipRequest { - fn eq(&self, other: &Self) -> bool { - self.0.imr_multiaddr.s_addr == other.0.imr_multiaddr.s_addr - && self.0.imr_interface.s_addr == other.0.imr_interface.s_addr - } -} -impl Eq for IpMembershipRequest {} - -impl fmt::Debug for IpMembershipRequest { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mref = &self.0.imr_multiaddr; - let maddr = mref.s_addr; - let iref = &self.0.imr_interface; - let ifaddr = iref.s_addr; - f.debug_struct("IpMembershipRequest") - .field("imr_multiaddr", &maddr) - .field("imr_interface", &ifaddr) - .finish() - } -} - /// Request for ipv6 multicast socket operations /// /// This is a wrapper type around `ipv6_mreq`. #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Ipv6MembershipRequest(libc::ipv6_mreq); impl Ipv6MembershipRequest { @@ -297,23 +259,6 @@ impl Ipv6MembershipRequest { } } -impl PartialEq for Ipv6MembershipRequest { - fn eq(&self, other: &Self) -> bool { - self.0.ipv6mr_multiaddr.s6_addr == other.0.ipv6mr_multiaddr.s6_addr && - self.0.ipv6mr_interface == other.0.ipv6mr_interface - } -} -impl Eq for Ipv6MembershipRequest {} - -impl fmt::Debug for Ipv6MembershipRequest { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Ipv6MembershipRequest") - .field("ipv6mr_multiaddr", &self.0.ipv6mr_multiaddr.s6_addr) - .field("ipv6mr_interface", &self.0.ipv6mr_interface) - .finish() - } -} - cfg_if! { // Darwin and DragonFly BSD always align struct cmsghdr to 32-bit only. if #[cfg(any(target_os = "dragonfly", target_os = "ios", target_os = "macos"))] { @@ -386,7 +331,7 @@ macro_rules! cmsg_space { /// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new(); /// ``` #[repr(C)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct CmsgSpace { _hdr: cmsghdr, _pad: [align_of_cmsg_data; 0], @@ -419,7 +364,7 @@ impl CmsgBuffer for Vec { } } -#[allow(missing_debug_implementations)] // msghdr isn't Debug +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct RecvMsg<'a> { pub bytes: usize, cmsghdr: Option<&'a cmsghdr>, @@ -439,7 +384,7 @@ impl<'a> RecvMsg<'a> { } } -#[allow(missing_debug_implementations)] // msghdr isn't Debug +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct CmsgIterator<'a> { /// Control message buffer to decode from. Must adhere to cmsg alignment. cmsghdr: Option<&'a cmsghdr>, @@ -478,7 +423,7 @@ impl<'a> Iterator for CmsgIterator<'a> { // alignment issues. // // See https://github.com/nix-rust/nix/issues/999 -#[allow(missing_debug_implementations)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum ControlMessageOwned { /// Received version of /// [`ControlMessage::ScmRights`][#enum.ControlMessage.html#variant.ScmRights] @@ -679,7 +624,7 @@ impl ControlMessageOwned { /// exhaustively pattern-match it. /// /// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html) -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ControlMessage<'a> { /// A message of type `SCM_RIGHTS`, containing an array of file /// descriptors passed between processes. @@ -742,7 +687,7 @@ pub enum ControlMessage<'a> { // An opaque structure used to prevent cmsghdr from being a public type #[doc(hidden)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct UnknownCmsg(cmsghdr, Vec); impl<'a> ControlMessage<'a> { diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 5f19e5f343..a996010018 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -173,7 +173,7 @@ macro_rules! sockopt_impl { }; (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => { - #[derive(Copy, Clone, Debug)] + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct $name; getsockopt_impl!($name, $level, $flag, $ty, $getter); @@ -184,14 +184,14 @@ macro_rules! sockopt_impl { }; (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => { - #[derive(Copy, Clone, Debug)] + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct $name; setsockopt_impl!($name, $level, $flag, $ty, $setter); }; (Both, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty, $setter:ty) => { - #[derive(Copy, Clone, Debug)] + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct $name; setsockopt_impl!($name, $level, $flag, $ty, $setter); diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs index de69ae51f8..e5980369d5 100644 --- a/src/sys/statvfs.rs +++ b/src/sys/statvfs.rs @@ -57,8 +57,7 @@ libc_bitflags!( /// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html). // FIXME: Replace with repr(transparent) #[repr(C)] -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct Statvfs(libc::statvfs); impl Statvfs { diff --git a/src/sys/sysinfo.rs b/src/sys/sysinfo.rs index 98ef7bd517..4c8e389888 100644 --- a/src/sys/sysinfo.rs +++ b/src/sys/sysinfo.rs @@ -6,8 +6,7 @@ use Result; use errno::Errno; /// System info structure returned by `sysinfo`. -#[derive(Copy, Clone)] -#[allow(missing_debug_implementations)] // libc::sysinfo doesn't impl Debug +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] pub struct SysInfo(libc::sysinfo); impl SysInfo { diff --git a/src/sys/termios.rs b/src/sys/termios.rs index d8815baa00..c7cdf10b46 100644 --- a/src/sys/termios.rs +++ b/src/sys/termios.rs @@ -176,8 +176,7 @@ use ::unistd::Pid; /// This is a wrapper around the `libc::termios` struct that provides a safe interface for the /// standard fields. The only safe way to obtain an instance of this struct is to extract it from /// an open port using `tcgetattr()`. -#[derive(Clone)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Termios { inner: RefCell, /// Input mode flags (see `termios.c_iflag` documentation) diff --git a/src/sys/time.rs b/src/sys/time.rs index 4bd3b7808d..3ad57543b1 100644 --- a/src/sys/time.rs +++ b/src/sys/time.rs @@ -45,7 +45,7 @@ pub trait TimeValLike: Sized { } #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct TimeSpec(timespec); const NANOS_PER_SEC: i64 = 1_000_000_000; @@ -67,25 +67,6 @@ impl AsRef for TimeSpec { } } -impl fmt::Debug for TimeSpec { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("TimeSpec") - .field("tv_sec", &self.tv_sec()) - .field("tv_nsec", &self.tv_nsec()) - .finish() - } -} - -impl PartialEq for TimeSpec { - // The implementation of cmp is simplified by assuming that the struct is - // normalized. That is, tv_nsec must always be within [0, 1_000_000_000) - fn eq(&self, other: &TimeSpec) -> bool { - self.tv_sec() == other.tv_sec() && self.tv_nsec() == other.tv_nsec() - } -} - -impl Eq for TimeSpec {} - impl Ord for TimeSpec { // The implementation of cmp is simplified by assuming that the struct is // normalized. That is, tv_nsec must always be within [0, 1_000_000_000) @@ -259,7 +240,7 @@ impl fmt::Display for TimeSpec { #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct TimeVal(timeval); const MICROS_PER_SEC: i64 = 1_000_000; @@ -278,25 +259,6 @@ impl AsRef for TimeVal { } } -impl fmt::Debug for TimeVal { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("TimeVal") - .field("tv_sec", &self.tv_sec()) - .field("tv_usec", &self.tv_usec()) - .finish() - } -} - -impl PartialEq for TimeVal { - // The implementation of cmp is simplified by assuming that the struct is - // normalized. That is, tv_usec must always be within [0, 1_000_000) - fn eq(&self, other: &TimeVal) -> bool { - self.tv_sec() == other.tv_sec() && self.tv_usec() == other.tv_usec() - } -} - -impl Eq for TimeVal {} - impl Ord for TimeVal { // The implementation of cmp is simplified by assuming that the struct is // normalized. That is, tv_usec must always be within [0, 1_000_000) diff --git a/src/sys/uio.rs b/src/sys/uio.rs index 45860be5aa..d089084eed 100644 --- a/src/sys/uio.rs +++ b/src/sys/uio.rs @@ -88,8 +88,7 @@ pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result{ /// and [`process_vm_writev`](fn.process_vm_writev.html). #[cfg(target_os = "linux")] #[repr(C)] -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct RemoteIoVec { /// The starting address of this slice (`iov_base`). pub base: usize, @@ -160,7 +159,7 @@ pub fn process_vm_readv(pid: ::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], remo } #[repr(C)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct IoVec(libc::iovec, PhantomData); impl IoVec { diff --git a/src/sys/utsname.rs b/src/sys/utsname.rs index e33d0739a0..ab09c7d232 100644 --- a/src/sys/utsname.rs +++ b/src/sys/utsname.rs @@ -4,8 +4,7 @@ use std::ffi::CStr; use std::str::from_utf8_unchecked; #[repr(C)] -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct UtsName(libc::utsname); impl UtsName { diff --git a/src/sys/wait.rs b/src/sys/wait.rs index 3f99757daf..c54f7ec579 100644 --- a/src/sys/wait.rs +++ b/src/sys/wait.rs @@ -55,7 +55,7 @@ libc_bitflags!( /// Note that there are two Linux-specific enum variants, `PtraceEvent` /// and `PtraceSyscall`. Portable code should avoid exhaustively /// matching on `WaitStatus`. -#[derive(Eq, PartialEq, Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum WaitStatus { /// The process exited normally (as with `exit()` or returning from /// `main`) with the given exit code. This case matches the C macro diff --git a/src/ucontext.rs b/src/ucontext.rs index c94464d570..5e10e7d1f8 100644 --- a/src/ucontext.rs +++ b/src/ucontext.rs @@ -6,8 +6,7 @@ use errno::Errno; use std::mem; use sys::signal::SigSet; -#[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct UContext { context: libc::ucontext_t, } diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 9cbf0257ce..7d945397b5 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -1,9 +1,11 @@ use nix::sys::socket::{InetAddr, UnixAddr, getsockname}; -use std::slice; +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6}; +use std::os::unix::io::RawFd; use std::path::Path; +use std::slice; use std::str::FromStr; -use std::os::unix::io::RawFd; use libc::c_char; use tempfile; @@ -66,6 +68,37 @@ pub fn test_path_to_sock_addr() { assert_eq!(addr.path(), Some(actual)); } +fn calculate_hash(t: &T) -> u64 { + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() +} + +#[test] +pub fn test_addr_equality_path() { + let path = "/foo/bar"; + let actual = Path::new(path); + let addr1 = UnixAddr::new(actual).unwrap(); + let mut addr2 = addr1.clone(); + + addr2.0.sun_path[10] = 127; + + assert_eq!(addr1, addr2); + assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2)); +} + +#[cfg(target_os = "linux")] +#[test] +pub fn test_addr_equality_abstract() { + let name = String::from("nix\0abstract\0test"); + let addr1 = UnixAddr::new_abstract(name.as_bytes()).unwrap(); + let mut addr2 = addr1.clone(); + addr2.0.sun_path[18] = 127; + + assert_eq!(addr1, addr2); + assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2)); +} + // Test getting/setting abstract addresses (without unix socket creation) #[cfg(target_os = "linux")] #[test] From b5c04adbd7df7f58fdecf8967d112632eac256b3 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 10 Mar 2019 18:30:09 -0700 Subject: [PATCH 3/6] Remove test of impl Debug for PollFd As this is now derived, having a test is unnecessary --- test/test_poll.rs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/test/test_poll.rs b/test/test_poll.rs index 6cac3b779a..aef40e4792 100644 --- a/test/test_poll.rs +++ b/test/test_poll.rs @@ -1,5 +1,5 @@ use nix::poll::{PollFlags, poll, PollFd}; -use nix::unistd::{write, pipe, close}; +use nix::unistd::{write, pipe}; #[test] fn test_poll() { @@ -19,24 +19,6 @@ fn test_poll() { assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN)); } -#[test] -fn test_poll_debug() { - assert_eq!(format!("{:?}", PollFd::new(0, PollFlags::empty())), - "PollFd { fd: 0, events: (empty), revents: (empty) }"); - assert_eq!(format!("{:?}", PollFd::new(1, PollFlags::POLLIN)), - "PollFd { fd: 1, events: POLLIN, revents: (empty) }"); - - // Testing revents requires doing some I/O - let (r, w) = pipe().unwrap(); - let mut fds = [PollFd::new(r, PollFlags::POLLIN)]; - write(w, b" ").unwrap(); - close(w).unwrap(); - poll(&mut fds, -1).unwrap(); - assert_eq!(format!("{:?}", fds[0]), - format!("PollFd {{ fd: {}, events: POLLIN, revents: POLLIN | POLLHUP }}", r)); - close(r).unwrap(); -} - // ppoll(2) is the same as poll except for how it handles timeouts and signals. // Repeating the test for poll(2) should be sufficient to check that our // bindings are correct. From 07420b59e38c04a14b78c634953c9c5687e82e81 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 10 Mar 2019 18:51:05 -0700 Subject: [PATCH 4/6] Improve debugging of mq tests by using assert_* macros --- test/test_mq.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/test_mq.rs b/test/test_mq.rs index 41ab358b33..caac4fc261 100644 --- a/test/test_mq.rs +++ b/test/test_mq.rs @@ -55,8 +55,8 @@ fn test_mq_getattr() { }; let mqd = r.unwrap(); - let read_attr = mq_getattr(mqd); - assert!(read_attr.unwrap() == initial_attr); + let read_attr = mq_getattr(mqd).unwrap(); + assert_eq!(read_attr, initial_attr); mq_close(mqd).unwrap(); } @@ -79,21 +79,21 @@ fn test_mq_setattr() { let mqd = r.unwrap(); let new_attr = MqAttr::new(0, 20, MSG_SIZE * 2, 100); - let old_attr = mq_setattr(mqd, &new_attr); - assert!(old_attr.unwrap() == initial_attr); + let old_attr = mq_setattr(mqd, &new_attr).unwrap(); + assert_eq!(old_attr, initial_attr); - let new_attr_get = mq_getattr(mqd); + let new_attr_get = mq_getattr(mqd).unwrap(); // The following tests make sense. No changes here because according to the Linux man page only // O_NONBLOCK can be set (see tests below) - assert!(new_attr_get.unwrap() != new_attr); + assert_ne!(new_attr_get, new_attr); let new_attr_non_blocking = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long, 10, MSG_SIZE, 0); mq_setattr(mqd, &new_attr_non_blocking).unwrap(); - let new_attr_get = mq_getattr(mqd); + let new_attr_get = mq_getattr(mqd).unwrap(); // now the O_NONBLOCK flag has been set - assert!(new_attr_get.unwrap() != initial_attr); - assert!(new_attr_get.unwrap() == new_attr_non_blocking); + assert_ne!(new_attr_get, initial_attr); + assert_eq!(new_attr_get, new_attr_non_blocking); mq_close(mqd).unwrap(); } From 3fdf3fe02d0a5816afc7b31db942cfe507e828d1 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 9 Jun 2019 10:33:47 -0700 Subject: [PATCH 5/6] Fix tests for abstract sockets Abstract paths should always be N-1 in length where N is the length of the `sun_path` field (first byte is \0). Given that, `UnixAddr::new_abstract()` should always return this N-1 length, not just the length of the string provided (the rest of the array will be \0s). --- src/sys/socket/addr.rs | 20 ++++++++++++++++++-- test/sys/test_socket.rs | 33 +++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index c698822761..e6c5f8ae58 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -551,7 +551,7 @@ impl UnixAddr { ret.sun_path.as_mut_ptr().offset(1) as *mut u8, path.len()); - Ok(UnixAddr(ret, path.len() + 1)) + Ok(UnixAddr(ret, ret.sun_path.len())) } } @@ -1126,9 +1126,11 @@ mod datalink { #[cfg(test)] mod tests { - #[cfg(any(target_os = "dragonfly", + #[cfg(any(target_os = "android", + target_os = "dragonfly", target_os = "freebsd", target_os = "ios", + target_os = "linux", target_os = "macos", target_os = "netbsd", target_os = "openbsd"))] @@ -1174,4 +1176,18 @@ mod tests { _ => { unreachable!() } }; } + + #[cfg(any(target_os = "android", target_os = "linux"))] + #[test] + fn test_abstract_sun_path() { + let name = String::from("nix\0abstract\0test"); + let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap(); + + let sun_path1 = addr.sun_path(); + let sun_path2 = [0u8, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + assert_eq!(sun_path1.len(), sun_path2.len()); + for i in 0..sun_path1.len() { + assert_eq!(sun_path1[i], sun_path2[i]); + } + } } diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 7d945397b5..12afc84cca 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -87,16 +87,27 @@ pub fn test_addr_equality_path() { assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2)); } -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +pub fn test_abstract_sun_path_too_long() { + let name = String::from("nix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0testttttnix\0abstract\0test\0make\0sure\0this\0is\0long\0enough"); + let addr = UnixAddr::new_abstract(name.as_bytes()); + assert!(addr.is_err()); +} + +#[cfg(any(target_os = "android", target_os = "linux"))] #[test] pub fn test_addr_equality_abstract() { let name = String::from("nix\0abstract\0test"); let addr1 = UnixAddr::new_abstract(name.as_bytes()).unwrap(); let mut addr2 = addr1.clone(); - addr2.0.sun_path[18] = 127; assert_eq!(addr1, addr2); assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2)); + + addr2.0.sun_path[18] = 127; + assert_ne!(addr1, addr2); + assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2)); } // Test getting/setting abstract addresses (without unix socket creation) @@ -105,20 +116,22 @@ pub fn test_addr_equality_abstract() { pub fn test_abstract_uds_addr() { let empty = String::new(); let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap(); - assert_eq!(addr.as_abstract(), Some(empty.as_bytes())); + let sun_path = [0u8; 107]; + assert_eq!(addr.as_abstract(), Some(&sun_path[..])); let name = String::from("nix\0abstract\0test"); let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap(); - assert_eq!(addr.as_abstract(), Some(name.as_bytes())); + let sun_path = [ + 110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + assert_eq!(addr.as_abstract(), Some(&sun_path[..])); assert_eq!(addr.path(), None); // Internally, name is null-prefixed (abstract namespace) - let internal: &[u8] = unsafe { - slice::from_raw_parts(addr.0.sun_path.as_ptr() as *const u8, addr.1) - }; - let mut abstract_name = name.clone(); - abstract_name.insert(0, '\0'); - assert_eq!(internal, abstract_name.as_bytes()); + assert_eq!(addr.0.sun_path[0], 0); } #[test] From 37929c7dafd86571730e4f566ef520cf0139e008 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 9 Jun 2019 11:27:44 -0700 Subject: [PATCH 6/6] Use ptr::NonNull for Dir This is a minor optimization that allows for reduced sizes of datatypes. Since this pointer will never be NULL, it's safe to use here --- src/dir.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dir.rs b/src/dir.rs index d4fc43a4d0..1820b5330f 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -27,8 +27,7 @@ use libc::{dirent, readdir_r}; /// does). #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Dir( - // This could be ptr::NonNull once nix requires Rust 1.25. - *mut libc::DIR + ptr::NonNull ); impl Dir { @@ -60,7 +59,8 @@ impl Dir { unsafe { libc::close(fd) }; return Err(e); }; - Ok(Dir(d)) + // Always guaranteed to be non-null by the previous check + Ok(Dir(ptr::NonNull::new(d).unwrap())) } /// Returns an iterator of `Result` which rewinds when finished. @@ -79,13 +79,13 @@ unsafe impl Send for Dir {} impl AsRawFd for Dir { fn as_raw_fd(&self) -> RawFd { - unsafe { libc::dirfd(self.0) } + unsafe { libc::dirfd(self.0.as_ptr()) } } } impl Drop for Dir { fn drop(&mut self) { - unsafe { libc::closedir(self.0) }; + unsafe { libc::closedir(self.0.as_ptr()) }; } } @@ -104,7 +104,7 @@ impl<'d> Iterator for Iter<'d> { // Probably fine here too then. let mut ent: Entry = Entry(::std::mem::uninitialized()); let mut result = ptr::null_mut(); - if let Err(e) = Errno::result(readdir_r((self.0).0, &mut ent.0, &mut result)) { + if let Err(e) = Errno::result(readdir_r((self.0).0.as_ptr(), &mut ent.0, &mut result)) { return Some(Err(e)); } if result == ptr::null_mut() { @@ -118,7 +118,7 @@ impl<'d> Iterator for Iter<'d> { impl<'d> Drop for Iter<'d> { fn drop(&mut self) { - unsafe { libc::rewinddir((self.0).0) } + unsafe { libc::rewinddir((self.0).0.as_ptr()) } } }