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..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 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 diff --git a/src/dir.rs b/src/dir.rs index 814e9e0c0b..1820b5330f 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,9 +25,9 @@ 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 + ptr::NonNull ); impl Dir { @@ -59,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. @@ -78,25 +79,17 @@ unsafe impl Send for Dir {} impl AsRawFd for Dir { fn as_raw_fd(&self) -> RawFd { - unsafe { libc::dirfd(self.0) } - } -} - -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() + 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()) }; } } -#[derive(Debug)] +#[derive(Debug, Eq, Hash, PartialEq)] pub struct Iter<'d>(&'d mut Dir); impl<'d> Iterator for Iter<'d> { @@ -111,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() { @@ -125,17 +118,17 @@ 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()) } } } /// 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..e6c5f8ae58 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 { @@ -648,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())) } } @@ -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,19 +1122,15 @@ 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)] 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"))] @@ -1484,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/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..12afc84cca 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,26 +68,70 @@ 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(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(); + + 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) #[cfg(target_os = "linux")] #[test] 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] 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(); } 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.