Snap for 8730993 from fdb16c9d501c4b6752f13c07c14d288e077a55f0 to mainline-tzdata3-release

Change-Id: Ide614347dd43b85d5e48e340f139bfb99e4319b3
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 90eb8fa..82a8727 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,5 @@
 {
   "git": {
-    "sha1": "afba7c5a33dd4fd62b047e64089487cf822ccec2"
-  },
-  "path_in_vcs": ""
-}
\ No newline at end of file
+    "sha1": "4c7021787a174493bf1abb90a711d7464e6c80f6"
+  }
+}
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..3d432e0
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+/CHANGELOG.md merge=union
diff --git a/Android.bp b/Android.bp
index 88940a1..50fe7cb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -25,22 +25,20 @@
     name: "libnix",
     host_supported: true,
     crate_name: "nix",
-    cargo_env_compat: true,
-    cargo_pkg_version: "0.23.1",
     srcs: ["src/lib.rs"],
     edition: "2018",
     rustlibs: [
         "libbitflags",
         "libcfg_if",
         "liblibc",
-        "libmemoffset",
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
-        "com.android.compos",
         "com.android.virt",
     ],
-    vendor_available: true,
-    min_sdk_version: "29",
 }
+
+// dependent_library ["feature_list"]
+//   bitflags-1.2.1 "default"
+//   cfg-if-1.0.0
+//   libc-0.2.94 "default,extra_traits,std"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77d5b2a..1297ba7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,216 +1,7 @@
 # Change Log
 
 All notable changes to this project will be documented in this file.
-This project adheres to [Semantic Versioning](https://semver.org/).
-
-## [0.23.1] - 2021-12-16
-
-### Added
-### Changed
-
-- Relaxed the bitflags requirement from 1.3.1 to 1.1.  This partially reverts
-  #1492.  From now on, the MSRV is not guaranteed to work with all versions of
-  all dependencies, just with some version of all dependencies.
-  (#[1607](https://github.com/nix-rust/nix/pull/1607))
-
-### Fixed
-
-- Fixed soundness issues in `FdSet::insert`, `FdSet::remove`, and
-  `FdSet::contains` involving file descriptors outside of the range
-  `0..FD_SETSIZE`.
-  (#[1575](https://github.com/nix-rust/nix/pull/1575))
-
-### Removed
-
-## [0.23.0] - 2021-09-28
-### Added
-
-- Added the `LocalPeerCred` sockopt.
-  (#[1482](https://github.com/nix-rust/nix/pull/1482))
-- Added `TimeSpec::from_duration` and `TimeSpec::from_timespec`
-  (#[1465](https://github.com/nix-rust/nix/pull/1465))
-- Added `IPV6_V6ONLY` sockopt.
-  (#[1470](https://github.com/nix-rust/nix/pull/1470))
-- Added `impl From<User> for libc::passwd` trait implementation to convert a `User`
-  into a `libc::passwd`. Consumes the `User` struct to give ownership over
-  the member pointers.
-  (#[1471](https://github.com/nix-rust/nix/pull/1471))
-- Added `pthread_kill`.
-  (#[1472](https://github.com/nix-rust/nix/pull/1472))
-- Added `mknodat`.
-  (#[1473](https://github.com/nix-rust/nix/pull/1473))
-- Added `setrlimit` and `getrlimit`.
-  (#[1302](https://github.com/nix-rust/nix/pull/1302))
-- Added `ptrace::interrupt` method for platforms that support `PTRACE_INTERRUPT`
-  (#[1422](https://github.com/nix-rust/nix/pull/1422))
-- Added `IP6T_SO_ORIGINAL_DST` sockopt.
-  (#[1490](https://github.com/nix-rust/nix/pull/1490))
-- Added the `PTRACE_EVENT_STOP` variant to the `sys::ptrace::Event` enum
-  (#[1335](https://github.com/nix-rust/nix/pull/1335))
-- Exposed `SockAddr::from_raw_sockaddr`
-  (#[1447](https://github.com/nix-rust/nix/pull/1447))
-- Added `TcpRepair`
-  (#[1503](https://github.com/nix-rust/nix/pull/1503))
-- Enabled `pwritev` and `preadv` for more operating systems.
-  (#[1511](https://github.com/nix-rust/nix/pull/1511))
-- Added support for `TCP_MAXSEG` TCP Maximum Segment Size socket options
-  (#[1292](https://github.com/nix-rust/nix/pull/1292))
-- Added `Ipv4RecvErr` and `Ipv6RecvErr` sockopts and associated control messages.
-  (#[1514](https://github.com/nix-rust/nix/pull/1514))
-- Added `AsRawFd` implementation on `PollFd`.
-  (#[1516](https://github.com/nix-rust/nix/pull/1516))
-- Added `Ipv4Ttl` and `Ipv6Ttl` sockopts.
-  (#[1515](https://github.com/nix-rust/nix/pull/1515))
-- Added `MAP_EXCL`, `MAP_ALIGNED_SUPER`, and `MAP_CONCEAL` mmap flags, and
-  exposed `MAP_ANONYMOUS` for all operating systems.
-  (#[1522](https://github.com/nix-rust/nix/pull/1522))
-  (#[1525](https://github.com/nix-rust/nix/pull/1525))
-  (#[1531](https://github.com/nix-rust/nix/pull/1531))
-  (#[1534](https://github.com/nix-rust/nix/pull/1534))
-- Added read/write accessors for 'events' on `PollFd`.
-  (#[1517](https://github.com/nix-rust/nix/pull/1517))
-
-### Changed
-
-- `FdSet::{contains, highest, fds}` no longer require a mutable reference.
-  (#[1464](https://github.com/nix-rust/nix/pull/1464))
-- `User::gecos` and corresponding `libc::passwd::pw_gecos` are supported on
-  64-bit Android, change conditional compilation to include the field in
-  64-bit Android builds
-  (#[1471](https://github.com/nix-rust/nix/pull/1471))
-- `eventfd`s are supported on Android, change conditional compilation to
-  include `sys::eventfd::eventfd` and `sys::eventfd::EfdFlags`for Android
-  builds.
-  (#[1481](https://github.com/nix-rust/nix/pull/1481))
-- Most enums that come from C, for example `Errno`, are now marked as
-  `#[non_exhaustive]`.
-  (#[1474](https://github.com/nix-rust/nix/pull/1474))
-- Many more functions, mostly contructors, are now `const`.
-  (#[1476](https://github.com/nix-rust/nix/pull/1476))
-  (#[1492](https://github.com/nix-rust/nix/pull/1492))
-- `sys::event::KEvent::filter` now returns a `Result` instead of being
-  infalliable.  The only cases where it will now return an error are cases
-  where it previously would've had undefined behavior.
-  (#[1484](https://github.com/nix-rust/nix/pull/1484))
-- Minimum supported Rust version is now 1.46.0.
-  ([#1492](https://github.com/nix-rust/nix/pull/1492))
-- Rework `UnixAddr` to encapsulate internals better in order to fix soundness
-  issues. No longer allows creating a `UnixAddr` from a raw `sockaddr_un`.
-  ([#1496](https://github.com/nix-rust/nix/pull/1496))
-- Raised bitflags to 1.3.0 and the MSRV to 1.46.0.
-  ([#1492](https://github.com/nix-rust/nix/pull/1492))
-
-### Fixed
-
-- `posix_fadvise` now returns errors in the conventional way, rather than as a
-  non-zero value in `Ok()`.
-  (#[1538](https://github.com/nix-rust/nix/pull/1538))
-- Added more errno definitions for better backwards compatibility with
-  Nix 0.21.0.
-  (#[1467](https://github.com/nix-rust/nix/pull/1467))
-- Fixed potential undefined behavior in `Signal::try_from` on some platforms.
-  (#[1484](https://github.com/nix-rust/nix/pull/1484))
-- Fixed buffer overflow in `unistd::getgrouplist`.
-  (#[1545](https://github.com/nix-rust/nix/pull/1545))
-
-
-### Removed
-
-- Removed a couple of termios constants on redox that were never actually
-  supported.
-  (#[1483](https://github.com/nix-rust/nix/pull/1483))
-- Removed `nix::sys::signal::NSIG`.  It was of dubious utility, and not correct
-  for all platforms.
-  (#[1484](https://github.com/nix-rust/nix/pull/1484))
-- Removed support for 32-bit Apple targets, since they've been dropped by both
-  Rustc and Xcode.
-  (#[1492](https://github.com/nix-rust/nix/pull/1492))
-- Deprecated `SockAddr/InetAddr::to_str` in favor of `ToString::to_string`
-  (#[1495](https://github.com/nix-rust/nix/pull/1495))
-- Removed `SigevNotify` on OpenBSD and Redox.
-  (#[1511](https://github.com/nix-rust/nix/pull/1511))
-
-## [0.22.0] - 9 July 2021
-### Added
-- Added `if_nameindex` (#[1445](https://github.com/nix-rust/nix/pull/1445))
-- Added `nmount` for FreeBSD.
-  (#[1453](https://github.com/nix-rust/nix/pull/1453))
-- Added `IpFreebind` socket option (sockopt) on Linux, Fuchsia and Android.
-  (#[1456](https://github.com/nix-rust/nix/pull/1456))
-- Added `TcpUserTimeout` socket option (sockopt) on Linux and Fuchsia.
-  (#[1457](https://github.com/nix-rust/nix/pull/1457))
-- Added `renameat2` for Linux
-  (#[1458](https://github.com/nix-rust/nix/pull/1458))
-- Added `RxqOvfl` support on Linux, Fuchsia and Android.
-  (#[1455](https://github.com/nix-rust/nix/pull/1455))
-
-### Changed
-- `ptsname_r` now returns a lossily-converted string in the event of bad UTF,
-  just like `ptsname`.
-  ([#1446](https://github.com/nix-rust/nix/pull/1446))
-- Nix's error type is now a simple wrapper around the platform's Errno.  This
-  means it is now `Into<std::io::Error>`.  It's also `Clone`, `Copy`, `Eq`, and
-  has a small fixed size.  It also requires less typing.  For example, the old
-  enum variant `nix::Error::Sys(nix::errno::Errno::EINVAL)` is now simply
-  `nix::Error::EINVAL`.
-  ([#1446](https://github.com/nix-rust/nix/pull/1446))
-
-### Fixed
-### Removed
-
-## [0.21.0] - 31 May 2021
-### Added
-- Added `getresuid` and `getresgid`
-  (#[1430](https://github.com/nix-rust/nix/pull/1430))
-- Added TIMESTAMPNS support for linux
-  (#[1402](https://github.com/nix-rust/nix/pull/1402))
-- Added `sendfile64` (#[1439](https://github.com/nix-rust/nix/pull/1439))
-- Added `MS_LAZYTIME` to `MsFlags`
-  (#[1437](https://github.com/nix-rust/nix/pull/1437))
-
-### Changed
-- Made `forkpty` unsafe, like `fork`
-  (#[1390](https://github.com/nix-rust/nix/pull/1390))
-- Made `Uid`, `Gid` and `Pid` methods `from_raw` and `as_raw` a `const fn`
-  (#[1429](https://github.com/nix-rust/nix/pull/1429))
-- Made `Uid::is_root` a `const fn`
-  (#[1429](https://github.com/nix-rust/nix/pull/1429))
-- `AioCb` is now always pinned.  Once a `libc::aiocb` gets sent to the kernel,
-  its address in memory must not change.  Nix now enforces that by using
-  `std::pin`.  Most users won't need to change anything, except when using
-  `aio_suspend`.  See that method's documentation for the new usage.
-  (#[1440](https://github.com/nix-rust/nix/pull/1440))
-- `LioCb` is now constructed using a distinct `LioCbBuilder` struct.  This
-  avoids a soundness issue with the old `LioCb`.  Usage is similar but
-  construction now uses the builder pattern.  See the documentation for
-  details.
-  (#[1440](https://github.com/nix-rust/nix/pull/1440))
-- Minimum supported Rust version is now 1.41.0.
-  ([#1440](https://github.com/nix-rust/nix/pull/1440))
-- Errno aliases are now associated consts on `Errno`, instead of consts in the
-  `errno` module.
-  (#[1452](https://github.com/nix-rust/nix/pull/1452))
-
-### Fixed
-- Allow `sockaddr_ll` size, as reported by the Linux kernel, to be smaller then it's definition
-  (#[1395](https://github.com/nix-rust/nix/pull/1395))
-- Fix spurious errors using `sendmmsg` with multiple cmsgs
-  (#[1414](https://github.com/nix-rust/nix/pull/1414))
-- Added `Errno::EOPNOTSUPP` to FreeBSD, where it was missing.
-  (#[1452](https://github.com/nix-rust/nix/pull/1452))
-
-### Removed
-
-- Removed `sys::socket::accept4` from Android arm because libc removed it in
-  version 0.2.87.
-  ([#1399](https://github.com/nix-rust/nix/pull/1399))
-- `AioCb::from_boxed_slice` and `AioCb::from_boxed_mut_slice` have been
-  removed.  They were useful with earlier versions of Rust, but should no
-  longer be needed now that async/await are available.  `AioCb`s now work
-  exclusively with borrowed buffers, not owned ones.
-  (#[1440](https://github.com/nix-rust/nix/pull/1440))
-- Removed some Errno values from platforms where they aren't actually defined.
-  (#[1452](https://github.com/nix-rust/nix/pull/1452))
+This project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [0.20.0] - 20 February 2021
 ### Added
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..55990c4
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,114 @@
+# Contributing to nix
+
+We're really glad you're interested in contributing to nix! This
+document has a few pointers and guidelines to help get you started.
+
+To have a welcoming and inclusive project, nix uses the Rust project's
+[Code of Conduct][conduct]. All contributors are expected to follow it.
+
+[conduct]: https://www.rust-lang.org/conduct.html
+
+
+# Issues
+
+We use GitHub's [issue tracker][issues].
+
+[issues]: https://github.com/nix-rust/nix/issues
+
+
+## Bug reports
+
+Before submitting a new bug report, please [search existing
+issues][issue-search] to see if there's something related. If not, just
+[open a new issue][new-issue]!
+
+As a reminder, the more information you can give in your issue, the
+easier it is to figure out how to fix it. For nix, this will likely
+include the OS and version, and the architecture.
+
+[issue-search]: https://github.com/nix-rust/nix/search?utf8=%E2%9C%93&q=is%3Aissue&type=Issues
+[new-issue]: https://github.com/nix-rust/nix/issues/new
+
+
+## Feature / API requests
+
+If you'd like a new API or feature added, please [open a new
+issue][new-issue] requesting it. As with reporting a bug, the more
+information you can provide, the better.
+
+
+## Labels
+
+We use labels to help manage issues. The structure is modeled after
+[Rust's issue labeling scheme][rust-labels]:
+- **A-**prefixed labels state which area of the project the issue
+  relates to
+- **E-**prefixed labels explain the level of experience necessary to fix the
+  issue
+- **O-**prefixed labels specify the OS for issues that are OS-specific
+- **R-**prefixed labels specify the architecture for issues that are
+  architecture-specific
+
+[rust-labels]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#issue-triage
+
+
+# Pull requests
+
+GitHub pull requests are the primary mechanism we use to change nix. GitHub itself has
+some [great documentation][pr-docs] on using the Pull Request feature. We use the 'fork and
+pull' model described there.
+
+Please make pull requests against the `master` branch.
+
+If you change the API by way of adding, removing or changing something or if
+you fix a bug, please add an appropriate note to the [change log][cl]. We
+follow the conventions of [Keep A CHANGELOG][kacl].
+
+[cl]: https://github.com/nix-rust/nix/blob/master/CHANGELOG.md
+[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad
+[pr-docs]: https://help.github.com/articles/using-pull-requests/
+
+## Testing
+
+nix has a test suite that you can run with `cargo test`. Ideally, we'd like pull
+requests to include tests where they make sense. For example, when fixing a bug,
+add a test that would have failed without the fix.
+
+After you've made your change, make sure the tests pass in your development
+environment. We also have [continuous integration set up on
+Cirrus-CI][cirrus-ci], which might find some issues on other platforms. The CI
+will run once you open a pull request.
+
+There is also infrastructure for running tests for other targets
+locally.  More information is available in the [CI Readme][ci-readme].
+
+[cirrus-ci]: https://cirrus-ci.com/github/nix-rust/nix
+[ci-readme]: ci/README.md
+
+### Disabling a test in the CI environment
+
+Sometimes there are features that cannot be tested in the CI environment.
+To stop a test from running under CI, add `skip_if_cirrus!()` to it. Please
+describe the reason it shouldn't run under CI, and a link to an issue if
+possible!
+
+## bors, the bot who merges all the PRs
+
+All pull requests are merged via [bors], an integration bot. After the
+pull request has been reviewed, the reviewer will leave a comment like
+
+> bors r+
+
+to let bors know that it was approved. Then bors will check that it passes
+tests when merged with the latest changes in the `master` branch, and
+merge if the tests succeed.
+
+[bors]: https://bors-ng.github.io/
+
+
+## API conventions
+
+If you're adding a new API, we have a [document with
+conventions][conventions] to use throughout the nix project.
+
+[conventions]: https://github.com/nix-rust/nix/blob/master/CONVENTIONS.md
diff --git a/CONVENTIONS.md b/CONVENTIONS.md
new file mode 100644
index 0000000..2461085
--- /dev/null
+++ b/CONVENTIONS.md
@@ -0,0 +1,86 @@
+# Conventions
+
+In order to achieve our goal of wrapping [libc][libc] code in idiomatic rust
+constructs with minimal performance overhead, we follow the following
+conventions.
+
+Note that, thus far, not all the code follows these conventions and not all
+conventions we try to follow have been documented here. If you find an instance
+of either, feel free to remedy the flaw by opening a pull request with
+appropriate changes or additions.
+
+## Change Log
+
+We follow the conventions laid out in [Keep A CHANGELOG][kacl].
+
+[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad
+
+## libc constants, functions and structs
+
+We do not define integer constants ourselves, but use or reexport them from the
+[libc crate][libc].
+
+We use the functions exported from [libc][libc] instead of writing our own
+`extern` declarations.
+
+We use the `struct` definitions from [libc][libc] internally instead of writing
+our own. If we want to add methods to a libc type, we use the newtype pattern.
+For example,
+
+```rust
+pub struct SigSet(libc::sigset_t);
+
+impl SigSet {
+    ...
+}
+```
+
+When creating newtypes, we use Rust's `CamelCase` type naming convention.
+
+## Bitflags
+
+Many C functions have flags parameters that are combined from constants using
+bitwise operations. We represent the types of these parameters by types defined
+using our `libc_bitflags!` macro, which is a convenience wrapper around the
+`bitflags!` macro from the [bitflags crate][bitflags] that brings in the
+constant value from `libc`.
+
+We name the type for a set of constants whose element's names start with `FOO_`
+`FooFlags`.
+
+For example,
+
+```rust
+libc_bitflags!{
+    pub struct ProtFlags: libc::c_int {
+        PROT_NONE;
+        PROT_READ;
+        PROT_WRITE;
+        PROT_EXEC;
+        #[cfg(any(target_os = "linux", target_os = "android"))]
+        PROT_GROWSDOWN;
+        #[cfg(any(target_os = "linux", target_os = "android"))]
+        PROT_GROWSUP;
+    }
+}
+```
+
+
+## Enumerations
+
+We represent sets of constants that are intended as mutually exclusive arguments
+to parameters of functions by [enumerations][enum].
+
+
+## Structures Initialized by libc Functions
+
+Whenever we need to use a [libc][libc] function to properly initialize a
+variable and said function allows us to use uninitialized memory, we use
+[`std::mem::MaybeUninit`][std_MaybeUninit] when defining the variable. This
+allows us to avoid the overhead incurred by zeroing or otherwise initializing
+the variable.
+
+[bitflags]: https://crates.io/crates/bitflags/
+[enum]: https://doc.rust-lang.org/reference.html#enumerations
+[libc]: https://crates.io/crates/libc/
+[std_MaybeUninit]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html
diff --git a/Cargo.toml b/Cargo.toml
index 122c1af..0562246 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,25 +3,25 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
+# to registry (e.g., crates.io) dependencies
 #
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
 
 [package]
 edition = "2018"
-rust-version = "1.46"
 name = "nix"
-version = "0.23.1"
+version = "0.20.0"
 authors = ["The nix-rust Project Developers"]
-include = ["src/**/*", "test/**/*", "LICENSE", "README.md", "CHANGELOG.md"]
+exclude = ["/.gitignore", "/.cirrus.yml", "/ci/*", "/Cross.toml", "/RELEASE_PROCEDURE.md", "/bors.toml"]
 description = "Rust friendly bindings to *nix APIs"
 categories = ["os::unix-apis"]
 license = "MIT"
 repository = "https://github.com/nix-rust/nix"
 [package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu", "aarch64-linux-android", "x86_64-apple-darwin", "aarch64-apple-ios", "x86_64-unknown-freebsd", "x86_64-unknown-openbsd", "x86_64-unknown-netbsd", "x86_64-unknown-dragonfly", "x86_64-fuchsia", "x86_64-unknown-redox", "x86_64-unknown-illumos"]
+targets = ["x86_64-unknown-linux-gnu", "aarch64-linux-android", "x86_64-apple-darwin", "aarch64-apple-ios", "x86_64-unknown-freebsd", "x86_64-unknown-openbsd", "x86_64-unknown-netbsd", "x86_64-unknown-dragonfly", "x86_64-fuchsia", "x86_64-unknown-redox"]
 
 [[test]]
 name = "test"
@@ -54,29 +54,24 @@
 version = "1.0"
 
 [dependencies.libc]
-version = "0.2.102"
+version = "0.2.82"
 features = ["extra_traits"]
-[dev-dependencies.assert-impl]
-version = "0.1"
+[dev-dependencies.bytes]
+version = "0.4.8"
 
 [dev-dependencies.lazy_static]
 version = "1.2"
 
-[dev-dependencies.parking_lot]
-version = "0.11.2"
-
 [dev-dependencies.rand]
-version = "0.8"
+version = "0.6"
 
 [dev-dependencies.semver]
-version = "1.0.0"
+version = "0.9.0"
 
 [dev-dependencies.tempfile]
-version = "3.2.0"
+version = "3.0.5"
 [target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dev-dependencies.caps]
 version = "0.5.1"
-[target."cfg(not(target_os = \"redox\"))".dependencies.memoffset]
-version = "0.6.3"
 [target."cfg(target_os = \"dragonfly\")".build-dependencies.cc]
 version = "1"
 [target."cfg(target_os = \"freebsd\")".dev-dependencies.sysctl]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index d2ca8ee..885fa10 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -2,13 +2,19 @@
 name        = "nix"
 description = "Rust friendly bindings to *nix APIs"
 edition     = "2018"
-version     = "0.23.1"
-rust-version = "1.46"
+version     = "0.20.0"
 authors     = ["The nix-rust Project Developers"]
 repository  = "https://github.com/nix-rust/nix"
 license     = "MIT"
 categories  = ["os::unix-apis"]
-include = ["src/**/*", "test/**/*", "LICENSE", "README.md", "CHANGELOG.md"]
+exclude     = [
+  "/.gitignore",
+  "/.cirrus.yml",
+  "/ci/*",
+  "/Cross.toml",
+  "/RELEASE_PROCEDURE.md",
+  "/bors.toml"
+]
 
 [package.metadata.docs.rs]
 targets = [
@@ -21,28 +27,23 @@
   "x86_64-unknown-netbsd",
   "x86_64-unknown-dragonfly",
   "x86_64-fuchsia",
-  "x86_64-unknown-redox",
-  "x86_64-unknown-illumos"
+  "x86_64-unknown-redox"
 ]
 
 [dependencies]
-libc = { version = "0.2.102", features = [ "extra_traits" ] }
+libc = { version = "0.2.82", features = [ "extra_traits" ] }
 bitflags = "1.1"
 cfg-if = "1.0"
 
-[target.'cfg(not(target_os = "redox"))'.dependencies]
-memoffset = "0.6.3"
-
 [target.'cfg(target_os = "dragonfly")'.build-dependencies]
 cc = "1"
 
 [dev-dependencies]
-assert-impl = "0.1"
+bytes = "0.4.8"
 lazy_static = "1.2"
-parking_lot = "0.11.2"
-rand = "0.8"
-tempfile = "3.2.0"
-semver = "1.0.0"
+rand = "0.6"
+tempfile = "3.0.5"
+semver = "0.9.0"
 
 [target.'cfg(any(target_os = "android", target_os = "linux"))'.dev-dependencies]
 caps = "0.5.1"
diff --git a/METADATA b/METADATA
index e0fef6c..a71ef07 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/nix/nix-0.23.1.crate"
+    value: "https://static.crates.io/crates/nix/nix-0.20.0.crate"
   }
-  version: "0.23.1"
+  version: "0.20.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2022
-    month: 3
-    day: 16
+    year: 2021
+    month: 4
+    day: 2
   }
 }
diff --git a/README.md b/README.md
index a8759f1..167d192 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Rust bindings to *nix APIs
 
 [![Cirrus Build Status](https://api.cirrus-ci.com/github/nix-rust/nix.svg)](https://cirrus-ci.com/github/nix-rust/nix)
-[![crates.io](https://img.shields.io/crates/v/nix.svg)](https://crates.io/crates/nix)
+[![crates.io](http://meritbadge.herokuapp.com/nix)](https://crates.io/crates/nix)
 
 [Documentation (Releases)](https://docs.rs/nix/)
 
@@ -17,7 +17,7 @@
 
 As an example of what Nix provides, examine the differences between what is
 exposed by libc and nix for the
-[gethostname](https://man7.org/linux/man-pages/man2/gethostname.2.html) system
+[gethostname](http://man7.org/linux/man-pages/man2/gethostname.2.html) system
 call:
 
 ```rust,ignore
@@ -68,26 +68,33 @@
   * aarch64-linux-android
   * arm-linux-androideabi
   * arm-unknown-linux-musleabi
+  * armv7-apple-ios
   * armv7-linux-androideabi
+  * armv7s-apple-ios
+  * i386-apple-ios
+  * i686-apple-darwin
   * i686-linux-android
   * powerpc-unknown-linux-gnu
   * s390x-unknown-linux-gnu
   * x86_64-apple-ios
   * x86_64-linux-android
-  * x86_64-unknown-illumos
   * x86_64-unknown-netbsd
 
 Tier 3:
   * x86_64-fuchsia
-  * x86_64-unknown-dragonfly
-  * x86_64-unknown-linux-gnux32
-  * x86_64-unknown-openbsd
   * x86_64-unknown-redox
+  * x86_64-unknown-linux-gnux32
 
-## Minimum Supported Rust Version (MSRV)
+## Usage
 
-nix is supported on Rust 1.46.0 and higher.  It's MSRV will not be
-changed in the future without bumping the major or minor version.
+`nix` requires Rust 1.40.0 or newer.
+
+To use `nix`, add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+nix = "0.20.0"
+```
 
 ## Contributing
 
diff --git a/TEST_MAPPING b/TEST_MAPPING
index b44b9e2..5d7fef5 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,102 +1,14 @@
 // Generated by update_crate_tests.py for tests that depend on this crate.
 {
-  "imports": [
-    {
-      "path": "external/rust/crates/tokio"
-    }
-  ],
   "presubmit": [
     {
-      "name": "ZipFuseTest"
-    },
-    {
-      "name": "apkdmverity.test"
-    },
-    {
-      "name": "authfs_device_test_src_lib"
-    },
-    {
-      "name": "diced_open_dice_cbor_test"
-    },
-    {
-      "name": "diced_sample_inputs_test"
-    },
-    {
-      "name": "diced_test"
-    },
-    {
-      "name": "diced_utils_test"
-    },
-    {
-      "name": "diced_vendor_test"
+      "name": "keystore2_test"
     },
     {
       "name": "keystore2_crypto_test_rust"
     },
     {
-      "name": "keystore2_selinux_concurrency_test"
-    },
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "keystore2_test_utils_test"
-    },
-    {
-      "name": "legacykeystore_test"
-    },
-    {
-      "name": "microdroid_manager_test"
-    },
-    {
-      "name": "virtualizationservice_device_test"
-    }
-  ],
-  "presubmit-rust": [
-    {
-      "name": "ZipFuseTest"
-    },
-    {
-      "name": "apkdmverity.test"
-    },
-    {
-      "name": "authfs_device_test_src_lib"
-    },
-    {
-      "name": "diced_open_dice_cbor_test"
-    },
-    {
-      "name": "diced_sample_inputs_test"
-    },
-    {
-      "name": "diced_test"
-    },
-    {
-      "name": "diced_utils_test"
-    },
-    {
-      "name": "diced_vendor_test"
-    },
-    {
-      "name": "keystore2_crypto_test_rust"
-    },
-    {
-      "name": "keystore2_selinux_concurrency_test"
-    },
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "keystore2_test_utils_test"
-    },
-    {
-      "name": "legacykeystore_test"
-    },
-    {
-      "name": "microdroid_manager_test"
-    },
-    {
-      "name": "virtualizationservice_device_test"
+      "name": "vpnprofilestore_test"
     }
   ]
 }
diff --git a/cargo2android.json b/cargo2android.json
index f8fb37c..42b7833 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,13 +1,9 @@
 {
   "apex-available": [
     "//apex_available:platform",
-    "com.android.bluetooth",
-    "com.android.compos",
     "com.android.virt"
   ],
   "dependencies": true,
   "device": true,
-  "min-sdk-version": "29",
-  "run": true,
-  "vendor-available": true
-}
+  "run": true
+}
\ No newline at end of file
diff --git a/patches/0001-Allow-android-compiled-binaries-to-use-timerfd.patch b/patches/0001-Allow-android-compiled-binaries-to-use-timerfd.patch
new file mode 100644
index 0000000..e164a3c
--- /dev/null
+++ b/patches/0001-Allow-android-compiled-binaries-to-use-timerfd.patch
@@ -0,0 +1,26 @@
+From e09a4f4e8661e8036819deb97dc1d9fcf2a49d2b Mon Sep 17 00:00:00 2001
+From: Zach Johnson <zachoverflow@google.com>
+Date: Tue, 17 Nov 2020 11:05:57 -0800
+Subject: [PATCH] Allow android compiled binaries to use timerfd
+
+Bug: 171749953
+Test: compile
+Change-Id: Iaf16615cf834df02537e3b569ab08dd98a497a70
+---
+ src/sys/mod.rs | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/sys/mod.rs b/src/sys/mod.rs
+index bf7f541..b8b9e6f 100644
+--- a/src/sys/mod.rs
++++ b/src/sys/mod.rs
+@@ -103,5 +103,5 @@ pub mod wait;
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ pub mod inotify;
+ 
+-#[cfg(target_os = "linux")]
++#[cfg(any(target_os = "android", target_os = "linux"))]
+ pub mod timerfd;
+-- 
+2.29.2.299.gdc1121823c-goog
+
diff --git a/src/dir.rs b/src/dir.rs
index ed70a45..7d4ab82 100644
--- a/src/dir.rs
+++ b/src/dir.rs
@@ -53,12 +53,14 @@
 
     /// Converts from a file descriptor, closing it on success or failure.
     pub fn from_fd(fd: RawFd) -> Result<Self> {
-        let d = ptr::NonNull::new(unsafe { libc::fdopendir(fd) }).ok_or_else(|| {
+        let d = unsafe { libc::fdopendir(fd) };
+        if d.is_null() {
             let e = Error::last();
             unsafe { libc::close(fd) };
-            e
-        })?;
-        Ok(Dir(d))
+            return Err(e);
+        };
+        // Always guaranteed to be non-null by the previous check
+        Ok(Dir(ptr::NonNull::new(d).unwrap()))
     }
 
     /// Returns an iterator of `Result<Entry>` which rewinds when finished.
@@ -84,7 +86,7 @@
 impl Drop for Dir {
     fn drop(&mut self) {
         let e = Errno::result(unsafe { libc::closedir(self.0.as_ptr()) });
-        if !std::thread::panicking() && e == Err(Errno::EBADF) {
+        if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
             panic!("Closing an invalid file descriptor!");
         };
     }
@@ -190,7 +192,6 @@
               target_os = "emscripten",
               target_os = "fuchsia",
               target_os = "haiku",
-              target_os = "illumos",
               target_os = "ios",
               target_os = "l4re",
               target_os = "linux",
@@ -205,13 +206,11 @@
                   target_os = "emscripten",
                   target_os = "fuchsia",
                   target_os = "haiku",
-                  target_os = "illumos",
                   target_os = "ios",
                   target_os = "l4re",
                   target_os = "linux",
                   target_os = "macos",
                   target_os = "solaris")))]
-    #[allow(clippy::useless_conversion)]    // Not useless on all OSes
     pub fn ino(&self) -> u64 {
         u64::from(self.0.d_fileno)
     }
@@ -227,7 +226,6 @@
     /// notably, some Linux filesystems don't implement this. The caller should use `stat` or
     /// `fstat` if this returns `None`.
     pub fn file_type(&self) -> Option<Type> {
-        #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
         match self.0.d_type {
             libc::DT_FIFO => Some(Type::Fifo),
             libc::DT_CHR => Some(Type::CharacterDevice),
@@ -238,9 +236,5 @@
             libc::DT_SOCK => Some(Type::Socket),
             /* libc::DT_UNKNOWN | */ _ => None,
         }
-
-        // illumos and Solaris systems do not have the d_type member at all:
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-        None
     }
 }
diff --git a/src/env.rs b/src/env.rs
index bcae287..f144dfe 100644
--- a/src/env.rs
+++ b/src/env.rs
@@ -1,25 +1,12 @@
-//! Environment variables
 use cfg_if::cfg_if;
-use std::fmt;
-
-/// Indicates that [`clearenv`] failed for some unknown reason
-#[derive(Clone, Copy, Debug)]
-pub struct ClearEnvError;
-
-impl fmt::Display for ClearEnvError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "clearenv failed")
-    }
-}
-
-impl std::error::Error for ClearEnvError {}
+use crate::{Error, Result};
 
 /// Clear the environment of all name-value pairs.
 ///
 /// On platforms where libc provides `clearenv()`, it will be used. libc's
 /// `clearenv()` is documented to return an error code but not set errno; if the
 /// return value indicates a failure, this function will return
-/// [`ClearEnvError`].
+/// `Error::UnsupportedOperation`.
 ///
 /// On platforms where libc does not provide `clearenv()`, a fallback
 /// implementation will be used that iterates over all environment variables and
@@ -38,7 +25,8 @@
 ///  `environ` is currently held. The latter is not an issue if the only other
 ///  environment access in the program is via `std::env`, but the requirement on
 ///  thread safety must still be upheld.
-pub unsafe fn clearenv() -> std::result::Result<(), ClearEnvError> {
+pub unsafe fn clearenv() -> Result<()> {
+    let ret;
     cfg_if! {
         if #[cfg(any(target_os = "fuchsia",
                      target_os = "wasi",
@@ -47,19 +35,19 @@
                      target_os = "linux",
                      target_os = "android",
                      target_os = "emscripten"))] {
-            let ret = libc::clearenv();
+            ret = libc::clearenv();
         } else {
             use std::env;
             for (name, _) in env::vars_os() {
                 env::remove_var(name);
             }
-            let ret = 0;
+            ret = 0;
         }
     }
 
     if ret == 0 {
         Ok(())
     } else {
-        Err(ClearEnvError)
+        Err(Error::UnsupportedOperation)
     }
 }
diff --git a/src/errno.rs b/src/errno.rs
index 3da246e..e5c7092 100644
--- a/src/errno.rs
+++ b/src/errno.rs
@@ -1,6 +1,5 @@
 use cfg_if::cfg_if;
 use libc::{c_int, c_void};
-use std::convert::TryFrom;
 use std::{fmt, io, error};
 use crate::{Error, Result};
 
@@ -26,10 +25,6 @@
         unsafe fn errno_location() -> *mut c_int {
             libc::__errno_location()
         }
-    } else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] {
-        unsafe fn errno_location() -> *mut c_int {
-            libc::___errno()
-        }
     }
 }
 
@@ -49,43 +44,6 @@
 }
 
 impl Errno {
-    /// Convert this `Error` to an [`Errno`](enum.Errno.html).
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # use nix::Error;
-    /// # use nix::errno::Errno;
-    /// let e = Error::from(Errno::EPERM);
-    /// assert_eq!(Some(Errno::EPERM), e.as_errno());
-    /// ```
-    #[deprecated(
-        since = "0.22.0",
-        note = "It's a no-op now; just delete it."
-    )]
-    pub const fn as_errno(self) -> Option<Self> {
-        Some(self)
-    }
-
-    /// Create a nix Error from a given errno
-    #[deprecated(
-        since = "0.22.0",
-        note = "It's a no-op now; just delete it."
-    )]
-    #[allow(clippy::wrong_self_convention)] // False positive
-    pub fn from_errno(errno: Errno) -> Error {
-        errno
-    }
-
-    /// Create a new invalid argument error (`EINVAL`)
-    #[deprecated(
-        since = "0.22.0",
-        note = "Use Errno::EINVAL instead"
-    )]
-    pub const fn invalid_argument() -> Error {
-        Errno::EINVAL
-    }
-
     pub fn last() -> Self {
         last()
     }
@@ -94,7 +52,7 @@
         desc(self)
     }
 
-    pub const fn from_i32(err: i32) -> Errno {
+    pub fn from_i32(err: i32) -> Errno {
         from_i32(err)
     }
 
@@ -104,29 +62,13 @@
 
     /// Returns `Ok(value)` if it does not contain the sentinel value. This
     /// should not be used when `-1` is not the errno sentinel value.
-    #[inline]
     pub fn result<S: ErrnoSentinel + PartialEq<S>>(value: S) -> Result<S> {
         if value == S::sentinel() {
-            Err(Self::last())
+            Err(Error::Sys(Self::last()))
         } else {
             Ok(value)
         }
     }
-
-    /// Backwards compatibility hack for Nix <= 0.21.0 users
-    ///
-    /// In older versions of Nix, `Error::Sys` was an enum variant.  Now it's a
-    /// function, which is compatible with most of the former use cases of the
-    /// enum variant.  But you should use `Error(Errno::...)` instead.
-    #[deprecated(
-        since = "0.22.0",
-        note = "Use Errno::... instead"
-    )]
-    #[allow(non_snake_case)]
-    #[inline]
-    pub const fn Sys(errno: Errno) -> Error {
-        errno
-    }
 }
 
 /// The sentinel value indicates that a function failed and more detailed
@@ -148,7 +90,7 @@
 }
 
 impl ErrnoSentinel for *mut c_void {
-    fn sentinel() -> Self { -1isize as *mut c_void }
+    fn sentinel() -> Self { (-1 as isize) as *mut c_void }
 }
 
 impl ErrnoSentinel for libc::sighandler_t {
@@ -169,16 +111,6 @@
     }
 }
 
-impl TryFrom<io::Error> for Errno {
-    type Error = io::Error;
-
-    fn try_from(ioerror: io::Error) -> std::result::Result<Self, io::Error> {
-        ioerror.raw_os_error()
-            .map(Errno::from_i32)
-            .ok_or(ioerror)
-    }
-}
-
 fn last() -> Errno {
     Errno::from_i32(errno())
 }
@@ -258,142 +190,114 @@
         EHOSTUNREACH    => "No route to host",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ECHRNG          => "Channel number out of range",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EL2NSYNC        => "Level 2 not synchronized",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EL3HLT          => "Level 3 halted",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EL3RST          => "Level 3 reset",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ELNRNG          => "Link number out of range",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EUNATCH         => "Protocol driver not attached",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ENOCSI          => "No CSI structure available",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EL2HLT          => "Level 2 halted",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EBADE           => "Invalid exchange",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EBADR           => "Invalid request descriptor",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EXFULL          => "Exchange full",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ENOANO          => "No anode",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EBADRQC         => "Invalid request code",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EBADSLT         => "Invalid slot",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EBFONT          => "Bad font file format",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ENOSTR          => "Device not a stream",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ENODATA         => "No data available",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ETIME           => "Timer expired",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ENOSR           => "Out of streams resources",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ENONET          => "Machine is not on the network",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ENOPKG          => "Package not installed",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EREMOTE         => "Object is remote",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ENOLINK         => "Link has been severed",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EADV            => "Advertise error",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ESRMNT          => "Srmount error",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ECOMM           => "Communication error on send",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EPROTO          => "Protocol error",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EMULTIHOP       => "Multihop attempted",
 
@@ -405,70 +309,55 @@
                   target_os = "fuchsia"))]
         EBADMSG         => "Not a data message",
 
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-        EBADMSG         => "Trying to read unreadable message",
-
         #[cfg(any(target_os = "linux", target_os = "android",
                   target_os = "fuchsia"))]
         EOVERFLOW       => "Value too large for defined data type",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ENOTUNIQ        => "Name not unique on network",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EBADFD          => "File descriptor in bad state",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EREMCHG         => "Remote address changed",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ELIBACC         => "Can not access a needed shared library",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ELIBBAD         => "Accessing a corrupted shared library",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ELIBSCN         => ".lib section in a.out corrupted",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ELIBMAX         => "Attempting to link in too many shared libraries",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ELIBEXEC        => "Cannot exec a shared library directly",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia", target_os = "openbsd"))]
         EILSEQ          => "Illegal byte sequence",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ERESTART        => "Interrupted system call should be restarted",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ESTRPIPE        => "Streams pipe error",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         EUSERS          => "Too many users",
 
@@ -515,7 +404,6 @@
         EMEDIUMTYPE     => "Wrong medium type",
 
         #[cfg(any(target_os = "linux", target_os = "android",
-                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ECANCELED       => "Operation canceled",
 
@@ -539,16 +427,10 @@
                   target_os = "fuchsia"))]
         EOWNERDEAD      => "Owner died",
 
-        #[cfg(any( target_os = "illumos", target_os = "solaris"))]
-        EOWNERDEAD      => "Process died with lock",
-
         #[cfg(any(target_os = "linux", target_os = "android",
                   target_os = "fuchsia"))]
         ENOTRECOVERABLE => "State not recoverable",
 
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-        ENOTRECOVERABLE => "Lock is not recoverable",
-
         #[cfg(any(all(target_os = "linux", not(target_arch="mips")),
                   target_os = "fuchsia"))]
         ERFKILL         => "Operation not possible due to RF-kill",
@@ -563,8 +445,7 @@
         #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "redox"))]
         EMULTIHOP       => "Multihop attempted",
 
-        #[cfg(any(target_os = "freebsd", target_os = "dragonfly",
-                  target_os = "redox"))]
+        #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "redox"))]
         ENOLINK         => "Link has been severed",
 
         #[cfg(target_os = "freebsd")]
@@ -581,8 +462,7 @@
         #[cfg(any(target_os = "macos", target_os = "freebsd",
                   target_os = "dragonfly", target_os = "ios",
                   target_os = "openbsd", target_os = "netbsd",
-                  target_os = "redox", target_os = "illumos",
-                  target_os = "solaris"))]
+                  target_os = "redox"))]
         EOVERFLOW       => "Value too large to be stored in data type",
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
@@ -608,7 +488,7 @@
         EPROTO          => "Protocol error",
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
-                  target_os = "ios", target_os = "openbsd"))]
+                  target_os = "ios", target_os = "openbsd", ))]
         ENOTRECOVERABLE => "State not recoverable",
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
@@ -617,8 +497,7 @@
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
                   target_os = "dragonfly", target_os = "ios",
-                  target_os = "openbsd", target_os = "netbsd",
-                  target_os = "illumos", target_os = "solaris"))]
+                  target_os = "openbsd", target_os = "netbsd"))]
         ENOTSUP         => "Operation not supported",
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
@@ -635,15 +514,13 @@
         #[cfg(any(target_os = "macos", target_os = "freebsd",
                   target_os = "dragonfly", target_os = "ios",
                   target_os = "openbsd", target_os = "netbsd",
-                  target_os = "redox", target_os = "illumos",
-                  target_os = "solaris"))]
+                  target_os = "redox"))]
         EDQUOT          => "Disc quota exceeded",
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
                   target_os = "dragonfly", target_os = "ios",
                   target_os = "openbsd", target_os = "netbsd",
-                  target_os = "redox", target_os = "illumos",
-                  target_os = "solaris"))]
+                  target_os = "redox"))]
         ESTALE          => "Stale NFS file handle",
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
@@ -711,16 +588,14 @@
         #[cfg(any(target_os = "macos", target_os = "ios"))]
         EBADMACHO       => "Malformed Macho file",
 
-        #[cfg(any(target_os = "macos", target_os = "ios",
-                  target_os = "netbsd"))]
+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
         EMULTIHOP       => "Reserved",
 
         #[cfg(any(target_os = "macos", target_os = "ios",
                   target_os = "netbsd", target_os = "redox"))]
         ENODATA         => "No message available on STREAM",
 
-        #[cfg(any(target_os = "macos", target_os = "ios",
-                  target_os = "netbsd"))]
+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
         ENOLINK         => "Reserved",
 
         #[cfg(any(target_os = "macos", target_os = "ios",
@@ -735,8 +610,7 @@
                   target_os = "netbsd", target_os = "redox"))]
         ETIME           => "STREAM ioctl timeout",
 
-        #[cfg(any(target_os = "macos", target_os = "ios",
-                  target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "macos", target_os = "ios"))]
         EOPNOTSUPP      => "Operation not supported on socket",
 
         #[cfg(any(target_os = "macos", target_os = "ios"))]
@@ -753,15 +627,6 @@
 
         #[cfg(target_os = "dragonfly")]
         EASYNC          => "Async",
-
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-        EDEADLOCK       => "Resource deadlock would occur",
-
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-        ELOCKUNMAPPED   => "Locked lock was unmapped",
-
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-        ENOTACTIVE      => "Facility is not active",
     }
 }
 
@@ -770,7 +635,6 @@
 mod consts {
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum Errno {
         UnknownErrno    = 0,
         EPERM           = libc::EPERM,
@@ -908,29 +772,11 @@
         EHWPOISON       = libc::EHWPOISON,
     }
 
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EWOULDBLOCK instead"
-    )]
     pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EDEADLOCK instead"
-    )]
     pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::ENOTSUP instead"
-    )]
-    pub const ENOTSUP:  Errno = Errno::EOPNOTSUPP;
+    pub const ENOTSUP:     Errno = Errno::EOPNOTSUPP;
 
-    impl Errno {
-        pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-        pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-        pub const ENOTSUP:     Errno = Errno::EOPNOTSUPP;
-    }
-
-    pub const fn from_i32(e: i32) -> Errno {
+    pub fn from_i32(e: i32) -> Errno {
         use self::Errno::*;
 
         match e {
@@ -1076,7 +922,6 @@
 mod consts {
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum Errno {
         UnknownErrno    = 0,
         EPERM           = libc::EPERM,
@@ -1187,29 +1032,13 @@
         EQFULL          = libc::EQFULL,
     }
 
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::ELAST instead"
-    )]
-    pub const ELAST:  Errno = Errno::EQFULL;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EWOULDBLOCK instead"
-    )]
+    pub const ELAST: Errno       = Errno::EQFULL;
     pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EDEADLOCK instead"
-    )]
     pub const EDEADLOCK:   Errno = Errno::EDEADLK;
 
-    impl Errno {
-        pub const ELAST: Errno       = Errno::EQFULL;
-        pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-        pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-    }
+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
 
-    pub const fn from_i32(e: i32) -> Errno {
+    pub fn from_i32(e: i32) -> Errno {
         use self::Errno::*;
 
         match e {
@@ -1328,7 +1157,6 @@
 mod consts {
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum Errno {
         UnknownErrno    = 0,
         EPERM           = libc::EPERM,
@@ -1429,35 +1257,13 @@
         EOWNERDEAD      = libc::EOWNERDEAD,
     }
 
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::ELAST instead"
-    )]
     pub const ELAST: Errno       = Errno::EOWNERDEAD;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EWOULDBLOCK instead"
-    )]
     pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EDEADLOCK instead"
-    )]
     pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EOPNOTSUPP instead"
-    )]
-    pub const EOPNOTSUPP:  Errno = Errno::ENOTSUP;
 
-    impl Errno {
-        pub const ELAST: Errno       = Errno::EOWNERDEAD;
-        pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-        pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-        pub const EOPNOTSUPP:  Errno = Errno::ENOTSUP;
-    }
+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
 
-    pub const fn from_i32(e: i32) -> Errno {
+    pub fn from_i32(e: i32) -> Errno {
         use self::Errno::*;
 
         match e {
@@ -1567,7 +1373,6 @@
 mod consts {
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum Errno {
         UnknownErrno    = 0,
         EPERM           = libc::EPERM,
@@ -1666,35 +1471,14 @@
         EASYNC          = libc::EASYNC,
     }
 
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::ELAST instead"
-    )]
     pub const ELAST: Errno       = Errno::EASYNC;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EWOULDBLOCK instead"
-    )]
     pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EDEADLOCK instead"
-    )]
     pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EOPNOTSUPP instead"
-    )]
     pub const EOPNOTSUPP:  Errno = Errno::ENOTSUP;
 
-    impl Errno {
-        pub const ELAST: Errno       = Errno::EASYNC;
-        pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-        pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-        pub const EOPNOTSUPP:  Errno = Errno::ENOTSUP;
-    }
+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
 
-    pub const fn from_i32(e: i32) -> Errno {
+    pub fn from_i32(e: i32) -> Errno {
         use self::Errno::*;
 
         match e {
@@ -1802,7 +1586,6 @@
 mod consts {
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum Errno {
         UnknownErrno    = 0,
         EPERM           = libc::EPERM,
@@ -1902,23 +1685,12 @@
         EPROTO          = libc::EPROTO,
     }
 
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::ELAST instead"
-    )]
     pub const ELAST: Errno       = Errno::ENOTSUP;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EWOULDBLOCK instead"
-    )]
     pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
 
-    impl Errno {
-        pub const ELAST: Errno       = Errno::ENOTSUP;
-        pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-    }
+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
 
-    pub const fn from_i32(e: i32) -> Errno {
+    pub fn from_i32(e: i32) -> Errno {
         use self::Errno::*;
 
         match e {
@@ -2026,7 +1798,6 @@
 mod consts {
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum Errno {
         UnknownErrno    = 0,
         EPERM           = libc::EPERM,
@@ -2127,23 +1898,12 @@
         EPROTO          = libc::EPROTO,
     }
 
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::ELAST instead"
-    )]
     pub const ELAST: Errno       = Errno::ENOTSUP;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EWOULDBLOCK instead"
-    )]
     pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
 
-    impl Errno {
-        pub const ELAST: Errno       = Errno::ENOTSUP;
-        pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-    }
+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
 
-    pub const fn from_i32(e: i32) -> Errno {
+    pub fn from_i32(e: i32) -> Errno {
         use self::Errno::*;
 
         match e {
@@ -2252,7 +2012,6 @@
 mod consts {
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum Errno {
         UnknownErrno = 0,
         EPERM = libc::EPERM,
@@ -2342,17 +2101,12 @@
         EPROTO = libc::EPROTO,
     }
 
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EWOULDBLOCK instead"
-    )]
+    pub const ELAST: Errno = Errno::UnknownErrno;
     pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
 
-    impl Errno {
-        pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-    }
+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
 
-    pub const fn from_i32(e: i32) -> Errno {
+    pub fn from_i32(e: i32) -> Errno {
         use self::Errno::*;
 
         match e {
@@ -2445,279 +2199,3 @@
         }
     }
 }
-
-#[cfg(any(target_os = "illumos", target_os = "solaris"))]
-mod consts {
-    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-    #[repr(i32)]
-    #[non_exhaustive]
-    pub enum Errno {
-        UnknownErrno = 0,
-        EPERM = libc::EPERM,
-        ENOENT = libc::ENOENT,
-        ESRCH = libc::ESRCH,
-        EINTR = libc::EINTR,
-        EIO = libc::EIO,
-        ENXIO = libc::ENXIO,
-        E2BIG = libc::E2BIG,
-        ENOEXEC = libc::ENOEXEC,
-        EBADF = libc::EBADF,
-        ECHILD = libc::ECHILD,
-        EAGAIN = libc::EAGAIN,
-        ENOMEM = libc::ENOMEM,
-        EACCES = libc::EACCES,
-        EFAULT = libc::EFAULT,
-        ENOTBLK = libc::ENOTBLK,
-        EBUSY = libc::EBUSY,
-        EEXIST = libc::EEXIST,
-        EXDEV = libc::EXDEV,
-        ENODEV = libc::ENODEV,
-        ENOTDIR = libc::ENOTDIR,
-        EISDIR = libc::EISDIR,
-        EINVAL = libc::EINVAL,
-        ENFILE = libc::ENFILE,
-        EMFILE = libc::EMFILE,
-        ENOTTY = libc::ENOTTY,
-        ETXTBSY = libc::ETXTBSY,
-        EFBIG = libc::EFBIG,
-        ENOSPC = libc::ENOSPC,
-        ESPIPE = libc::ESPIPE,
-        EROFS = libc::EROFS,
-        EMLINK = libc::EMLINK,
-        EPIPE = libc::EPIPE,
-        EDOM = libc::EDOM,
-        ERANGE = libc::ERANGE,
-        ENOMSG = libc::ENOMSG,
-        EIDRM = libc::EIDRM,
-        ECHRNG = libc::ECHRNG,
-        EL2NSYNC = libc::EL2NSYNC,
-        EL3HLT = libc::EL3HLT,
-        EL3RST = libc::EL3RST,
-        ELNRNG = libc::ELNRNG,
-        EUNATCH = libc::EUNATCH,
-        ENOCSI = libc::ENOCSI,
-        EL2HLT = libc::EL2HLT,
-        EDEADLK = libc::EDEADLK,
-        ENOLCK = libc::ENOLCK,
-        ECANCELED = libc::ECANCELED,
-        ENOTSUP = libc::ENOTSUP,
-        EDQUOT = libc::EDQUOT,
-        EBADE = libc::EBADE,
-        EBADR = libc::EBADR,
-        EXFULL = libc::EXFULL,
-        ENOANO = libc::ENOANO,
-        EBADRQC = libc::EBADRQC,
-        EBADSLT = libc::EBADSLT,
-        EDEADLOCK = libc::EDEADLOCK,
-        EBFONT = libc::EBFONT,
-        EOWNERDEAD = libc::EOWNERDEAD,
-        ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
-        ENOSTR = libc::ENOSTR,
-        ENODATA = libc::ENODATA,
-        ETIME = libc::ETIME,
-        ENOSR = libc::ENOSR,
-        ENONET = libc::ENONET,
-        ENOPKG = libc::ENOPKG,
-        EREMOTE = libc::EREMOTE,
-        ENOLINK = libc::ENOLINK,
-        EADV = libc::EADV,
-        ESRMNT = libc::ESRMNT,
-        ECOMM = libc::ECOMM,
-        EPROTO = libc::EPROTO,
-        ELOCKUNMAPPED = libc::ELOCKUNMAPPED,
-        ENOTACTIVE = libc::ENOTACTIVE,
-        EMULTIHOP = libc::EMULTIHOP,
-        EBADMSG = libc::EBADMSG,
-        ENAMETOOLONG = libc::ENAMETOOLONG,
-        EOVERFLOW = libc::EOVERFLOW,
-        ENOTUNIQ = libc::ENOTUNIQ,
-        EBADFD = libc::EBADFD,
-        EREMCHG = libc::EREMCHG,
-        ELIBACC = libc::ELIBACC,
-        ELIBBAD = libc::ELIBBAD,
-        ELIBSCN = libc::ELIBSCN,
-        ELIBMAX = libc::ELIBMAX,
-        ELIBEXEC = libc::ELIBEXEC,
-        EILSEQ = libc::EILSEQ,
-        ENOSYS = libc::ENOSYS,
-        ELOOP = libc::ELOOP,
-        ERESTART = libc::ERESTART,
-        ESTRPIPE = libc::ESTRPIPE,
-        ENOTEMPTY = libc::ENOTEMPTY,
-        EUSERS = libc::EUSERS,
-        ENOTSOCK = libc::ENOTSOCK,
-        EDESTADDRREQ = libc::EDESTADDRREQ,
-        EMSGSIZE = libc::EMSGSIZE,
-        EPROTOTYPE = libc::EPROTOTYPE,
-        ENOPROTOOPT = libc::ENOPROTOOPT,
-        EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
-        ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
-        EOPNOTSUPP = libc::EOPNOTSUPP,
-        EPFNOSUPPORT = libc::EPFNOSUPPORT,
-        EAFNOSUPPORT = libc::EAFNOSUPPORT,
-        EADDRINUSE = libc::EADDRINUSE,
-        EADDRNOTAVAIL = libc::EADDRNOTAVAIL,
-        ENETDOWN = libc::ENETDOWN,
-        ENETUNREACH = libc::ENETUNREACH,
-        ENETRESET = libc::ENETRESET,
-        ECONNABORTED = libc::ECONNABORTED,
-        ECONNRESET = libc::ECONNRESET,
-        ENOBUFS = libc::ENOBUFS,
-        EISCONN = libc::EISCONN,
-        ENOTCONN = libc::ENOTCONN,
-        ESHUTDOWN = libc::ESHUTDOWN,
-        ETOOMANYREFS = libc::ETOOMANYREFS,
-        ETIMEDOUT = libc::ETIMEDOUT,
-        ECONNREFUSED = libc::ECONNREFUSED,
-        EHOSTDOWN = libc::EHOSTDOWN,
-        EHOSTUNREACH = libc::EHOSTUNREACH,
-        EALREADY = libc::EALREADY,
-        EINPROGRESS = libc::EINPROGRESS,
-        ESTALE = libc::ESTALE,
-    }
-
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::ELAST instead"
-    )]
-    pub const ELAST: Errno = Errno::ELAST;
-    #[deprecated(
-        since = "0.22.1",
-        note = "use nix::errno::Errno::EWOULDBLOCK instead"
-    )]
-    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-
-    impl Errno {
-        pub const ELAST: Errno       = Errno::ESTALE;
-        pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-    }
-
-    pub const fn from_i32(e: i32) -> Errno {
-        use self::Errno::*;
-
-        match e {
-            libc::EPERM => EPERM,
-            libc::ENOENT => ENOENT,
-            libc::ESRCH => ESRCH,
-            libc::EINTR => EINTR,
-            libc::EIO => EIO,
-            libc::ENXIO => ENXIO,
-            libc::E2BIG => E2BIG,
-            libc::ENOEXEC => ENOEXEC,
-            libc::EBADF => EBADF,
-            libc::ECHILD => ECHILD,
-            libc::EAGAIN => EAGAIN,
-            libc::ENOMEM => ENOMEM,
-            libc::EACCES => EACCES,
-            libc::EFAULT => EFAULT,
-            libc::ENOTBLK => ENOTBLK,
-            libc::EBUSY => EBUSY,
-            libc::EEXIST => EEXIST,
-            libc::EXDEV => EXDEV,
-            libc::ENODEV => ENODEV,
-            libc::ENOTDIR => ENOTDIR,
-            libc::EISDIR => EISDIR,
-            libc::EINVAL => EINVAL,
-            libc::ENFILE => ENFILE,
-            libc::EMFILE => EMFILE,
-            libc::ENOTTY => ENOTTY,
-            libc::ETXTBSY => ETXTBSY,
-            libc::EFBIG => EFBIG,
-            libc::ENOSPC => ENOSPC,
-            libc::ESPIPE => ESPIPE,
-            libc::EROFS => EROFS,
-            libc::EMLINK => EMLINK,
-            libc::EPIPE => EPIPE,
-            libc::EDOM => EDOM,
-            libc::ERANGE => ERANGE,
-            libc::ENOMSG => ENOMSG,
-            libc::EIDRM => EIDRM,
-            libc::ECHRNG => ECHRNG,
-            libc::EL2NSYNC => EL2NSYNC,
-            libc::EL3HLT => EL3HLT,
-            libc::EL3RST => EL3RST,
-            libc::ELNRNG => ELNRNG,
-            libc::EUNATCH => EUNATCH,
-            libc::ENOCSI => ENOCSI,
-            libc::EL2HLT => EL2HLT,
-            libc::EDEADLK => EDEADLK,
-            libc::ENOLCK => ENOLCK,
-            libc::ECANCELED => ECANCELED,
-            libc::ENOTSUP => ENOTSUP,
-            libc::EDQUOT => EDQUOT,
-            libc::EBADE => EBADE,
-            libc::EBADR => EBADR,
-            libc::EXFULL => EXFULL,
-            libc::ENOANO => ENOANO,
-            libc::EBADRQC => EBADRQC,
-            libc::EBADSLT => EBADSLT,
-            libc::EDEADLOCK => EDEADLOCK,
-            libc::EBFONT => EBFONT,
-            libc::EOWNERDEAD => EOWNERDEAD,
-            libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
-            libc::ENOSTR => ENOSTR,
-            libc::ENODATA => ENODATA,
-            libc::ETIME => ETIME,
-            libc::ENOSR => ENOSR,
-            libc::ENONET => ENONET,
-            libc::ENOPKG => ENOPKG,
-            libc::EREMOTE => EREMOTE,
-            libc::ENOLINK => ENOLINK,
-            libc::EADV => EADV,
-            libc::ESRMNT => ESRMNT,
-            libc::ECOMM => ECOMM,
-            libc::EPROTO => EPROTO,
-            libc::ELOCKUNMAPPED => ELOCKUNMAPPED,
-            libc::ENOTACTIVE => ENOTACTIVE,
-            libc::EMULTIHOP => EMULTIHOP,
-            libc::EBADMSG => EBADMSG,
-            libc::ENAMETOOLONG => ENAMETOOLONG,
-            libc::EOVERFLOW => EOVERFLOW,
-            libc::ENOTUNIQ => ENOTUNIQ,
-            libc::EBADFD => EBADFD,
-            libc::EREMCHG => EREMCHG,
-            libc::ELIBACC => ELIBACC,
-            libc::ELIBBAD => ELIBBAD,
-            libc::ELIBSCN => ELIBSCN,
-            libc::ELIBMAX => ELIBMAX,
-            libc::ELIBEXEC => ELIBEXEC,
-            libc::EILSEQ => EILSEQ,
-            libc::ENOSYS => ENOSYS,
-            libc::ELOOP => ELOOP,
-            libc::ERESTART => ERESTART,
-            libc::ESTRPIPE => ESTRPIPE,
-            libc::ENOTEMPTY => ENOTEMPTY,
-            libc::EUSERS => EUSERS,
-            libc::ENOTSOCK => ENOTSOCK,
-            libc::EDESTADDRREQ => EDESTADDRREQ,
-            libc::EMSGSIZE => EMSGSIZE,
-            libc::EPROTOTYPE => EPROTOTYPE,
-            libc::ENOPROTOOPT => ENOPROTOOPT,
-            libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
-            libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
-            libc::EOPNOTSUPP => EOPNOTSUPP,
-            libc::EPFNOSUPPORT => EPFNOSUPPORT,
-            libc::EAFNOSUPPORT => EAFNOSUPPORT,
-            libc::EADDRINUSE => EADDRINUSE,
-            libc::EADDRNOTAVAIL => EADDRNOTAVAIL,
-            libc::ENETDOWN => ENETDOWN,
-            libc::ENETUNREACH => ENETUNREACH,
-            libc::ENETRESET => ENETRESET,
-            libc::ECONNABORTED => ECONNABORTED,
-            libc::ECONNRESET => ECONNRESET,
-            libc::ENOBUFS => ENOBUFS,
-            libc::EISCONN => EISCONN,
-            libc::ENOTCONN => ENOTCONN,
-            libc::ESHUTDOWN => ESHUTDOWN,
-            libc::ETOOMANYREFS => ETOOMANYREFS,
-            libc::ETIMEDOUT => ETIMEDOUT,
-            libc::ECONNREFUSED => ECONNREFUSED,
-            libc::EHOSTDOWN => EHOSTDOWN,
-            libc::EHOSTUNREACH => EHOSTUNREACH,
-            libc::EALREADY => EALREADY,
-            libc::EINPROGRESS => EINPROGRESS,
-            libc::ESTALE => ESTALE,
-            _ => UnknownErrno,
-        }
-    }
-}
diff --git a/src/fcntl.rs b/src/fcntl.rs
index dd8e59a..d2242da 100644
--- a/src/fcntl.rs
+++ b/src/fcntl.rs
@@ -34,8 +34,6 @@
         AT_NO_AUTOMOUNT;
         #[cfg(any(target_os = "android", target_os = "linux"))]
         AT_EMPTY_PATH;
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-        AT_EACCESS;
     }
 }
 
@@ -50,7 +48,6 @@
         /// Open the file in append-only mode.
         O_APPEND;
         /// Generate a signal when input or output becomes possible.
-        #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
         O_ASYNC;
         /// Closes the file descriptor once an `execve` call is made.
         ///
@@ -66,7 +63,6 @@
                   target_os = "netbsd"))]
         O_DIRECT;
         /// If the specified path isn't a directory, fail.
-        #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
         O_DIRECTORY;
         /// Implicitly follow each `write()` with an `fdatasync()`.
         #[cfg(any(target_os = "android",
@@ -166,7 +162,7 @@
 );
 
 // The conversion is not identical on all operating systems.
-#[allow(clippy::useless_conversion)]
+#[allow(clippy::identity_conversion)]
 pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
     let fd = path.with_nix_path(|cstr| {
         unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
@@ -176,7 +172,7 @@
 }
 
 // The conversion is not identical on all operating systems.
-#[allow(clippy::useless_conversion)]
+#[allow(clippy::identity_conversion)]
 #[cfg(not(target_os = "redox"))]
 pub fn openat<P: ?Sized + NixPath>(
     dirfd: RawFd,
@@ -210,43 +206,6 @@
     Errno::result(res).map(drop)
 }
 
-#[cfg(all(
-    target_os = "linux",
-    target_env = "gnu",
-))]
-libc_bitflags! {
-    pub struct RenameFlags: u32 {
-        RENAME_EXCHANGE;
-        RENAME_NOREPLACE;
-        RENAME_WHITEOUT;
-    }
-}
-
-#[cfg(all(
-    target_os = "linux",
-    target_env = "gnu",
-))]
-pub fn renameat2<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
-    old_dirfd: Option<RawFd>,
-    old_path: &P1,
-    new_dirfd: Option<RawFd>,
-    new_path: &P2,
-    flags: RenameFlags,
-) -> Result<()> {
-    let res = old_path.with_nix_path(|old_cstr| {
-        new_path.with_nix_path(|new_cstr| unsafe {
-            libc::renameat2(
-                at_rawfd(old_dirfd),
-                old_cstr.as_ptr(),
-                at_rawfd(new_dirfd),
-                new_cstr.as_ptr(),
-                flags.bits(),
-            )
-        })
-    })??;
-    Errno::result(res).map(drop)
-}
-
 fn wrap_readlink_result(mut v: Vec<u8>, len: ssize_t) -> Result<OsString> {
     unsafe { v.set_len(len as usize) }
     v.shrink_to_fit();
@@ -289,19 +248,8 @@
     }
     // Uh oh, the result is too long...
     // Let's try to ask lstat how many bytes to allocate.
-    let reported_size = match dirfd {
-        #[cfg(target_os = "redox")]
-        Some(_) => unreachable!(),
-        #[cfg(any(target_os = "android", target_os = "linux"))]
-        Some(dirfd) => {
-            let flags = if path.is_empty() { AtFlags::AT_EMPTY_PATH } else { AtFlags::empty() };
-            super::sys::stat::fstatat(dirfd, path, flags | AtFlags::AT_SYMLINK_NOFOLLOW)
-        },
-        #[cfg(not(any(target_os = "android", target_os = "linux", target_os = "redox")))]
-        Some(dirfd) => super::sys::stat::fstatat(dirfd, path, AtFlags::AT_SYMLINK_NOFOLLOW),
-        None => super::sys::stat::lstat(path)
-    }
-        .map(|x| x.st_size)
+    let reported_size = super::sys::stat::lstat(path)
+        .and_then(|x| Ok(x.st_size))
         .unwrap_or(0);
     let mut try_size = if reported_size > 0 {
         // Note: even if `lstat`'s apparently valid answer turns out to be
@@ -325,7 +273,7 @@
                 Some(next_size) => try_size = next_size,
                 // It's absurd that this would happen, but handle it sanely
                 // anyway.
-                None => break Err(Errno::ENAMETOOLONG),
+                None => break Err(super::Error::Sys(Errno::ENAMETOOLONG)),
             }
         }
     }
@@ -374,7 +322,6 @@
 
 #[cfg(not(target_os = "redox"))]
 #[derive(Debug, Eq, Hash, PartialEq)]
-#[non_exhaustive]
 pub enum FcntlArg<'a> {
     F_DUPFD(RawFd),
     F_DUPFD_CLOEXEC(RawFd),
@@ -406,7 +353,6 @@
 
 #[cfg(target_os = "redox")]
 #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
-#[non_exhaustive]
 pub enum FcntlArg {
     F_DUPFD(RawFd),
     F_DUPFD_CLOEXEC(RawFd),
@@ -456,7 +402,6 @@
 }
 
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[non_exhaustive]
 pub enum FlockArg {
     LockShared,
     LockExclusive,
@@ -646,12 +591,12 @@
 ))]
 mod posix_fadvise {
     use crate::errno::Errno;
+    use libc;
     use std::os::unix::io::RawFd;
     use crate::Result;
 
     libc_enum! {
         #[repr(i32)]
-        #[non_exhaustive]
         pub enum PosixFadviseAdvice {
             POSIX_FADV_NORMAL,
             POSIX_FADV_SEQUENTIAL,
@@ -667,14 +612,9 @@
         offset: libc::off_t,
         len: libc::off_t,
         advice: PosixFadviseAdvice,
-    ) -> Result<()> {
+    ) -> Result<libc::c_int> {
         let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) };
-
-        if res == 0 {
-            Ok(())
-        } else {
-            Err(Errno::from_i32(res))
-        }
+        Errno::result(res)
     }
 }
 
@@ -691,6 +631,6 @@
     match Errno::result(res) {
         Err(err) => Err(err),
         Ok(0) => Ok(()),
-        Ok(errno) => Err(Errno::from_i32(errno)),
+        Ok(errno) => Err(crate::Error::Sys(Errno::from_i32(errno))),
     }
 }
diff --git a/src/features.rs b/src/features.rs
index ed80fd7..6b1cff5 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -94,28 +94,13 @@
     }
 }
 
-#[cfg(any(
-        target_os = "dragonfly",    // Since ???
-        target_os = "freebsd",      // Since 10.0
-        target_os = "illumos",      // Since ???
-        target_os = "netbsd",       // Since 6.0
-        target_os = "openbsd",      // Since 5.7
-        target_os = "redox",        // Since 1-july-2020
-))]
+#[cfg(any(target_os = "macos", target_os = "freebsd",
+          target_os = "dragonfly", target_os = "ios",
+          target_os = "openbsd", target_os = "netbsd",
+          target_os = "redox", target_os = "fuchsia"))]
 mod os {
     /// Check if the OS supports atomic close-on-exec for sockets
-    pub const fn socket_atomic_cloexec() -> bool {
-        true
-    }
-}
-
-#[cfg(any(target_os = "macos",
-          target_os = "ios",
-          target_os = "fuchsia",
-          target_os = "solaris"))]
-mod os {
-    /// Check if the OS supports atomic close-on-exec for sockets
-    pub const fn socket_atomic_cloexec() -> bool {
+    pub fn socket_atomic_cloexec() -> bool {
         false
     }
 }
diff --git a/src/kmod.rs b/src/kmod.rs
index c42068c..8789cb6 100644
--- a/src/kmod.rs
+++ b/src/kmod.rs
@@ -2,6 +2,7 @@
 //!
 //! For more details see
 
+use libc;
 use std::ffi::CStr;
 use std::os::unix::io::AsRawFd;
 
@@ -41,7 +42,7 @@
 /// init_module(&mut contents, &CString::new("who=Rust when=Now,12").unwrap()).unwrap();
 /// ```
 ///
-/// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
+/// See [`man init_module(2)`](http://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
 pub fn init_module(module_image: &[u8], param_values: &CStr) -> Result<()> {
     let res = unsafe {
         libc::syscall(
@@ -78,7 +79,7 @@
 /// finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()).unwrap();
 /// ```
 ///
-/// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
+/// See [`man init_module(2)`](http://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
 pub fn finit_module<T: AsRawFd>(fd: &T, param_values: &CStr, flags: ModuleInitFlags) -> Result<()> {
     let res = unsafe {
         libc::syscall(
@@ -95,7 +96,7 @@
 libc_bitflags!(
     /// Flags used by `delete_module`.
     ///
-    /// See [`man delete_module(2)`](https://man7.org/linux/man-pages/man2/delete_module.2.html)
+    /// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html)
     /// for a detailed description how these flags work.
     pub struct DeleteModuleFlags: libc::c_int {
         O_NONBLOCK;
@@ -114,7 +115,7 @@
 /// delete_module(&CString::new("mymod").unwrap(), DeleteModuleFlags::O_NONBLOCK).unwrap();
 /// ```
 ///
-/// See [`man delete_module(2)`](https://man7.org/linux/man-pages/man2/delete_module.2.html) for more information.
+/// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html) for more information.
 pub fn delete_module(name: &CStr, flags: DeleteModuleFlags) -> Result<()> {
     let res = unsafe { libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits()) };
 
diff --git a/src/lib.rs b/src/lib.rs
index 3a2b63a..e62c158 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,13 +5,15 @@
 #![crate_name = "nix"]
 #![cfg(unix)]
 #![allow(non_camel_case_types)]
+// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
+// warnings even though the macro expands into something with allow(dead_code)
+#![allow(dead_code)]
 #![cfg_attr(test, deny(warnings))]
 #![recursion_limit = "500"]
 #![deny(unused)]
 #![deny(unstable_features)]
 #![deny(missing_copy_implementations)]
 #![deny(missing_debug_implementations)]
-#![warn(missing_docs)]
 
 // Re-exported external crates
 pub use libc;
@@ -21,14 +23,13 @@
 
 // Public crates
 #[cfg(not(target_os = "redox"))]
-#[allow(missing_docs)]
 pub mod dir;
 pub mod env;
-#[allow(missing_docs)]
 pub mod errno;
+#[deny(missing_docs)]
 pub mod features;
-#[allow(missing_docs)]
 pub mod fcntl;
+#[deny(missing_docs)]
 #[cfg(any(target_os = "android",
           target_os = "dragonfly",
           target_os = "freebsd",
@@ -36,15 +37,12 @@
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
-          target_os = "illumos",
           target_os = "openbsd"))]
 pub mod ifaddrs;
 #[cfg(any(target_os = "android",
           target_os = "linux"))]
-#[allow(missing_docs)]
 pub mod kmod;
 #[cfg(any(target_os = "android",
-          target_os = "freebsd",
           target_os = "linux"))]
 pub mod mount;
 #[cfg(any(target_os = "dragonfly",
@@ -52,24 +50,23 @@
           target_os = "fushsia",
           target_os = "linux",
           target_os = "netbsd"))]
-#[allow(missing_docs)]
 pub mod mqueue;
+#[deny(missing_docs)]
 #[cfg(not(target_os = "redox"))]
 pub mod net;
+#[deny(missing_docs)]
 pub mod poll;
+#[deny(missing_docs)]
 #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
 pub mod pty;
 pub mod sched;
 pub mod sys;
-#[allow(missing_docs)]
 pub mod time;
 // This can be implemented for other platforms as soon as libc
 // provides bindings for them.
 #[cfg(all(target_os = "linux",
           any(target_arch = "x86", target_arch = "x86_64")))]
-#[allow(missing_docs)]
 pub mod ucontext;
-#[allow(missing_docs)]
 pub mod unistd;
 
 /*
@@ -80,7 +77,7 @@
 
 use libc::{c_char, PATH_MAX};
 
-use std::{ptr, result};
+use std::{error, fmt, ptr, result};
 use std::ffi::{CStr, OsStr};
 use std::os::unix::ffi::OsStrExt;
 use std::path::{Path, PathBuf};
@@ -88,31 +85,89 @@
 use errno::Errno;
 
 /// Nix Result Type
-pub type Result<T> = result::Result<T, Errno>;
+pub type Result<T> = result::Result<T, Error>;
 
-/// Nix's main error type.
+/// Nix Error Type
 ///
-/// It's a wrapper around Errno.  As such, it's very interoperable with
-/// [`std::io::Error`], but it has the advantages of:
-/// * `Clone`
-/// * `Copy`
-/// * `Eq`
-/// * Small size
-/// * Represents all of the system's errnos, instead of just the most common
-/// ones.
-pub type Error = Errno;
+/// The nix error type provides a common way of dealing with
+/// various system system/libc calls that might fail.  Each
+/// 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, Eq, PartialEq)]
+pub enum Error {
+    Sys(Errno),
+    InvalidPath,
+    /// The operation involved a conversion to Rust's native String type, which failed because the
+    /// string did not contain all valid UTF-8.
+    InvalidUtf8,
+    /// The operation is not supported by Nix, in this instance either use the libc bindings or
+    /// consult the module documentation to see if there is a more appropriate interface available.
+    UnsupportedOperation,
+}
 
-/// Common trait used to represent file system paths by many Nix functions.
+impl Error {
+    /// Convert this `Error` to an [`Errno`](enum.Errno.html).
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use nix::Error;
+    /// # use nix::errno::Errno;
+    /// let e = Error::from(Errno::EPERM);
+    /// assert_eq!(Some(Errno::EPERM), e.as_errno());
+    /// ```
+    pub fn as_errno(self) -> Option<Errno> {
+        if let Error::Sys(e) = self {
+            Some(e)
+        } else {
+            None
+        }
+    }
+
+    /// Create a nix Error from a given errno
+    pub fn from_errno(errno: Errno) -> Error {
+        Error::Sys(errno)
+    }
+
+    /// Get the current errno and convert it to a nix Error
+    pub fn last() -> Error {
+        Error::Sys(Errno::last())
+    }
+
+    /// Create a new invalid argument error (`EINVAL`)
+    pub fn invalid_argument() -> Error {
+        Error::Sys(Errno::EINVAL)
+    }
+
+}
+
+impl From<Errno> for Error {
+    fn from(errno: Errno) -> Error { Error::from_errno(errno) }
+}
+
+impl From<std::string::FromUtf8Error> for Error {
+    fn from(_: std::string::FromUtf8Error) -> Error { Error::InvalidUtf8 }
+}
+
+impl error::Error for Error {}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::InvalidPath => write!(f, "Invalid path"),
+            Error::InvalidUtf8 => write!(f, "Invalid UTF-8 string"),
+            Error::UnsupportedOperation => write!(f, "Unsupported Operation"),
+            Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
+        }
+    }
+}
+
 pub trait NixPath {
-    /// Is the path empty?
     fn is_empty(&self) -> bool;
 
-    /// Length of the path in bytes
     fn len(&self) -> usize;
 
-    /// Execute a function with this path as a `CStr`.
-    ///
-    /// Mostly used internally by Nix.
     fn with_nix_path<T, F>(&self, f: F) -> Result<T>
         where F: FnOnce(&CStr) -> T;
 }
@@ -160,7 +215,7 @@
             where F: FnOnce(&CStr) -> T {
         // Equivalence with the [u8] impl.
         if self.len() >= PATH_MAX as usize {
-            return Err(Errno::ENAMETOOLONG)
+            return Err(Error::InvalidPath);
         }
 
         Ok(f(self))
@@ -181,11 +236,11 @@
         let mut buf = [0u8; PATH_MAX as usize];
 
         if self.len() >= PATH_MAX as usize {
-            return Err(Errno::ENAMETOOLONG)
+            return Err(Error::InvalidPath);
         }
 
         match self.iter().position(|b| *b == 0) {
-            Some(_) => Err(Errno::EINVAL),
+            Some(_) => Err(Error::InvalidPath),
             None => {
                 unsafe {
                     // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
diff --git a/src/macros.rs b/src/macros.rs
index 3ccbfdd..feb02ea 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -83,9 +83,9 @@
 macro_rules! libc_enum {
     // Exit rule.
     (@make_enum
-        name: $BitFlags:ident,
         {
             $v:vis
+            name: $BitFlags:ident,
             attrs: [$($attrs:tt)*],
             entries: [$($entries:tt)*],
         }
@@ -97,98 +97,38 @@
         }
     };
 
-    // Exit rule including TryFrom
-    (@make_enum
-        name: $BitFlags:ident,
-        {
-            $v:vis
-            attrs: [$($attrs:tt)*],
-            entries: [$($entries:tt)*],
-            from_type: $repr:path,
-            try_froms: [$($try_froms:tt)*]
-        }
-    ) => {
-        $($attrs)*
-        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-        $v enum $BitFlags {
-            $($entries)*
-        }
-        impl ::std::convert::TryFrom<$repr> for $BitFlags {
-            type Error = $crate::Error;
-            #[allow(unused_doc_comments)]
-            fn try_from(x: $repr) -> $crate::Result<Self> {
-                match x {
-                    $($try_froms)*
-                    _ => Err($crate::Error::EINVAL)
-                }
-            }
-        }
-    };
-
     // Done accumulating.
     (@accumulate_entries
-        name: $BitFlags:ident,
         {
             $v:vis
+            name: $BitFlags:ident,
             attrs: $attrs:tt,
         },
-        $entries:tt,
-        $try_froms:tt;
+        $entries:tt;
     ) => {
         libc_enum! {
             @make_enum
-            name: $BitFlags,
             {
                 $v
+                name: $BitFlags,
                 attrs: $attrs,
                 entries: $entries,
             }
         }
     };
 
-    // Done accumulating and want TryFrom
-    (@accumulate_entries
-        name: $BitFlags:ident,
-        {
-            $v:vis
-            attrs: $attrs:tt,
-            from_type: $repr:path,
-        },
-        $entries:tt,
-        $try_froms:tt;
-    ) => {
-        libc_enum! {
-            @make_enum
-            name: $BitFlags,
-            {
-                $v
-                attrs: $attrs,
-                entries: $entries,
-                from_type: $repr,
-                try_froms: $try_froms
-            }
-        }
-    };
-
     // Munch an attr.
     (@accumulate_entries
-        name: $BitFlags:ident,
         $prefix:tt,
-        [$($entries:tt)*],
-        [$($try_froms:tt)*];
+        [$($entries:tt)*];
         #[$attr:meta] $($tail:tt)*
     ) => {
         libc_enum! {
             @accumulate_entries
-            name: $BitFlags,
             $prefix,
             [
                 $($entries)*
                 #[$attr]
-            ],
-            [
-                $($try_froms)*
-                #[$attr]
             ];
             $($tail)*
         }
@@ -196,47 +136,32 @@
 
     // Munch last ident if not followed by a comma.
     (@accumulate_entries
-        name: $BitFlags:ident,
         $prefix:tt,
-        [$($entries:tt)*],
-        [$($try_froms:tt)*];
+        [$($entries:tt)*];
         $entry:ident
     ) => {
         libc_enum! {
             @accumulate_entries
-            name: $BitFlags,
             $prefix,
             [
                 $($entries)*
                 $entry = libc::$entry,
-            ],
-            [
-                $($try_froms)*
-                libc::$entry => Ok($BitFlags::$entry),
             ];
         }
     };
 
     // Munch an ident; covers terminating comma case.
     (@accumulate_entries
-        name: $BitFlags:ident,
         $prefix:tt,
-        [$($entries:tt)*],
-        [$($try_froms:tt)*];
-        $entry:ident,
-        $($tail:tt)*
+        [$($entries:tt)*];
+        $entry:ident, $($tail:tt)*
     ) => {
         libc_enum! {
             @accumulate_entries
-            name: $BitFlags,
             $prefix,
             [
                 $($entries)*
                 $entry = libc::$entry,
-            ],
-            [
-                $($try_froms)*
-                libc::$entry => Ok($BitFlags::$entry),
             ];
             $($tail)*
         }
@@ -244,24 +169,16 @@
 
     // Munch an ident and cast it to the given type; covers terminating comma.
     (@accumulate_entries
-        name: $BitFlags:ident,
         $prefix:tt,
-        [$($entries:tt)*],
-        [$($try_froms:tt)*];
-        $entry:ident as $ty:ty,
-        $($tail:tt)*
+        [$($entries:tt)*];
+        $entry:ident as $ty:ty, $($tail:tt)*
     ) => {
         libc_enum! {
             @accumulate_entries
-            name: $BitFlags,
             $prefix,
             [
                 $($entries)*
                 $entry = libc::$entry as $ty,
-            ],
-            [
-                $($try_froms)*
-                libc::$entry as $ty => Ok($BitFlags::$entry),
             ];
             $($tail)*
         }
@@ -276,36 +193,26 @@
     ) => {
         libc_enum! {
             @accumulate_entries
-            name: $BitFlags,
             {
                 $v
+                name: $BitFlags,
                 attrs: [$(#[$attr])*],
             },
-            [],
             [];
             $($vals)*
         }
     };
+}
 
-    // Entry rule including TryFrom
-    (
-        $(#[$attr:meta])*
-        $v:vis enum $BitFlags:ident {
-            $($vals:tt)*
+/// A Rust version of the familiar C `offset_of` macro.  It returns the byte
+/// offset of `field` within struct `ty`
+#[cfg(not(target_os = "redox"))]
+macro_rules! offset_of {
+    ($ty:ty, $field:ident) => {{
+        // Safe because we don't actually read from the dereferenced pointer
+        #[allow(unused_unsafe)] // for when the macro is used in an unsafe block
+        unsafe {
+            &(*(ptr::null() as *const $ty)).$field as *const _ as usize
         }
-        impl TryFrom<$repr:path>
-    ) => {
-        libc_enum! {
-            @accumulate_entries
-            name: $BitFlags,
-            {
-                $v
-                attrs: [$(#[$attr])*],
-                from_type: $repr,
-            },
-            [],
-            [];
-            $($vals)*
-        }
-    };
+    }}
 }
diff --git a/src/mount/linux.rs b/src/mount.rs
similarity index 97%
rename from src/mount/linux.rs
rename to src/mount.rs
index 4cb2fa5..2c54761 100644
--- a/src/mount/linux.rs
+++ b/src/mount.rs
@@ -1,4 +1,3 @@
-#![allow(missing_docs)]
 use libc::{self, c_ulong, c_int};
 use crate::{Result, NixPath};
 use crate::errno::Errno;
@@ -39,7 +38,6 @@
         MS_KERNMOUNT;
         MS_I_VERSION;
         MS_STRICTATIME;
-        MS_LAZYTIME;
         MS_ACTIVE;
         MS_NOUSER;
         MS_RMT_MASK;
diff --git a/src/mount/bsd.rs b/src/mount/bsd.rs
deleted file mode 100644
index 627bfa5..0000000
--- a/src/mount/bsd.rs
+++ /dev/null
@@ -1,426 +0,0 @@
-use crate::{
-    Error,
-    Errno,
-    NixPath,
-    Result,
-    sys::uio::IoVec
-};
-use libc::{c_char, c_int, c_uint, c_void};
-use std::{
-    borrow::Cow,
-    ffi::{CString, CStr},
-    fmt,
-    io,
-    ptr
-};
-
-
-libc_bitflags!(
-    /// Used with [`Nmount::nmount`].
-    pub struct MntFlags: c_int {
-        /// ACL support enabled.
-        #[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
-        MNT_ACLS;
-        /// All I/O to the file system should be done asynchronously.
-        MNT_ASYNC;
-        /// dir should instead be a file system ID encoded as “FSID:val0:val1”.
-        #[cfg(target_os = "freebsd")]
-        MNT_BYFSID;
-        /// Force a read-write mount even if the file system appears to be
-        /// unclean.
-        MNT_FORCE;
-        /// GEOM journal support enabled.
-        #[cfg(target_os = "freebsd")]
-        MNT_GJOURNAL;
-        /// MAC support for objects.
-        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
-        MNT_MULTILABEL;
-        /// Disable read clustering.
-        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-        MNT_NOCLUSTERR;
-        /// Disable write clustering.
-        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-        MNT_NOCLUSTERW;
-        /// Enable NFS version 4 ACLs.
-        #[cfg(target_os = "freebsd")]
-        MNT_NFS4ACLS;
-        /// Do not update access times.
-        MNT_NOATIME;
-        /// Disallow program execution.
-        MNT_NOEXEC;
-        /// Do not honor setuid or setgid bits on files when executing them.
-        MNT_NOSUID;
-        /// Do not follow symlinks.
-        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-        MNT_NOSYMFOLLOW;
-        /// Mount read-only.
-        MNT_RDONLY;
-        /// Causes the vfs subsystem to update its data structures pertaining to
-        /// the specified already mounted file system.
-        MNT_RELOAD;
-        /// Create a snapshot of the file system.
-        ///
-        /// See [mksnap_ffs(8)](https://www.freebsd.org/cgi/man.cgi?query=mksnap_ffs)
-        #[cfg(any(target_os = "macos", target_os = "freebsd"))]
-        MNT_SNAPSHOT;
-        /// Using soft updates.
-        #[cfg(any(
-                target_os = "dragonfly",
-                target_os = "freebsd",
-                target_os = "netbsd",
-                target_os = "openbsd"
-        ))]
-        MNT_SOFTDEP;
-        /// Directories with the SUID bit set chown new files to their own
-        /// owner.
-        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-        MNT_SUIDDIR;
-        /// All I/O to the file system should be done synchronously.
-        MNT_SYNCHRONOUS;
-        /// Union with underlying fs.
-        #[cfg(any(
-                target_os = "macos",
-                target_os = "freebsd",
-                target_os = "netbsd"
-        ))]
-        MNT_UNION;
-        /// Indicates that the mount command is being applied to an already
-        /// mounted file system.
-        MNT_UPDATE;
-        /// Check vnode use counts.
-        #[cfg(target_os = "freebsd")]
-        MNT_NONBUSY;
-    }
-);
-
-
-/// The Error type of [`Nmount::nmount`].
-///
-/// It wraps an [`Errno`], but also may contain an additional message returned
-/// by `nmount(2)`.
-#[derive(Debug)]
-pub struct NmountError {
-    errno: Error,
-    errmsg: Option<String>
-}
-
-impl NmountError {
-    /// Returns the additional error string sometimes generated by `nmount(2)`.
-    pub fn errmsg(&self) -> Option<&str> {
-        self.errmsg.as_deref()
-    }
-
-    /// Returns the inner [`Error`]
-    pub const fn error(&self) -> Error {
-        self.errno
-    }
-
-    fn new(error: Error, errmsg: Option<&CStr>) -> Self {
-        Self {
-            errno: error,
-            errmsg: errmsg.map(CStr::to_string_lossy).map(Cow::into_owned)
-        }
-    }
-}
-
-impl std::error::Error for NmountError {}
-
-impl fmt::Display for NmountError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if let Some(errmsg) = &self.errmsg {
-            write!(f, "{:?}: {}: {}", self.errno, errmsg, self.errno.desc())
-        } else {
-            write!(f, "{:?}: {}", self.errno, self.errno.desc())
-        }
-    }
-}
-
-impl From<NmountError> for io::Error {
-    fn from(err: NmountError) -> Self {
-        err.errno.into()
-    }
-}
-
-/// Result type of [`Nmount::nmount`].
-pub type NmountResult = std::result::Result<(), NmountError>;
-
-/// Mount a FreeBSD file system.
-///
-/// The `nmount(2)` system call works similarly to the `mount(8)` program; it
-/// takes its options as a series of name-value pairs.  Most of the values are
-/// strings, as are all of the names.  The `Nmount` structure builds up an
-/// argument list and then executes the syscall.
-///
-/// # Examples
-///
-/// To mount `target` onto `mountpoint` with `nullfs`:
-/// ```
-/// # use nix::unistd::Uid;
-/// # use ::sysctl::CtlValue;
-/// # if !Uid::current().is_root() && CtlValue::Int(0) == ::sysctl::value("vfs.usermount").unwrap() {
-/// #     return;
-/// # };
-/// use nix::mount::{MntFlags, Nmount, unmount};
-/// use std::ffi::CString;
-/// use tempfile::tempdir;
-///
-/// let mountpoint = tempdir().unwrap();
-/// let target = tempdir().unwrap();
-///
-/// let fstype = CString::new("fstype").unwrap();
-/// let nullfs = CString::new("nullfs").unwrap();
-/// Nmount::new()
-///     .str_opt(&fstype, &nullfs)
-///     .str_opt_owned("fspath", mountpoint.path().to_str().unwrap())
-///     .str_opt_owned("target", target.path().to_str().unwrap())
-///     .nmount(MntFlags::empty()).unwrap();
-/// 
-/// unmount(mountpoint.path(), MntFlags::empty()).unwrap();
-/// ```
-///
-/// # See Also
-/// * [`nmount(2)`](https://www.freebsd.org/cgi/man.cgi?query=nmount)
-/// * [`nullfs(5)`](https://www.freebsd.org/cgi/man.cgi?query=nullfs)
-#[cfg(target_os = "freebsd")]
-#[derive(Debug, Default)]
-pub struct Nmount<'a>{
-    iov: Vec<IoVec<&'a [u8]>>,
-    is_owned: Vec<bool>,
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> Nmount<'a> {
-    /// Add an opaque mount option.
-    ///
-    /// Some file systems take binary-valued mount options.  They can be set
-    /// with this method.
-    ///
-    /// # Safety
-    ///
-    /// Unsafe because it will cause `Nmount::nmount` to dereference a raw
-    /// pointer.  The user is responsible for ensuring that `val` is valid and
-    /// its lifetime outlives `self`!  An easy way to do that is to give the
-    /// value a larger scope than `name`
-    ///
-    /// # Examples
-    /// ```
-    /// use libc::c_void;
-    /// use nix::mount::Nmount;
-    /// use std::ffi::CString;
-    /// use std::mem;
-    ///
-    /// // Note that flags outlives name
-    /// let mut flags: u32 = 0xdeadbeef;
-    /// let name = CString::new("flags").unwrap();
-    /// let p = &mut flags as *mut u32 as *mut c_void;
-    /// let len = mem::size_of_val(&flags);
-    /// let mut nmount = Nmount::new();
-    /// unsafe { nmount.mut_ptr_opt(&name, p, len) };
-    /// ```
-    pub unsafe fn mut_ptr_opt(
-        &mut self,
-        name: &'a CStr,
-        val: *mut c_void,
-        len: usize
-    ) -> &mut Self
-    {
-        self.iov.push(IoVec::from_slice(name.to_bytes_with_nul()));
-        self.is_owned.push(false);
-        self.iov.push(IoVec::from_raw_parts(val, len));
-        self.is_owned.push(false);
-        self
-    }
-
-    /// Add a mount option that does not take a value.
-    ///
-    /// # Examples
-    /// ```
-    /// use nix::mount::Nmount;
-    /// use std::ffi::CString;
-    ///
-    /// let read_only = CString::new("ro").unwrap();
-    /// Nmount::new()
-    ///     .null_opt(&read_only);
-    /// ```
-    pub fn null_opt(&mut self, name: &'a CStr) -> &mut Self {
-        self.iov.push(IoVec::from_slice(name.to_bytes_with_nul()));
-        self.is_owned.push(false);
-        self.iov.push(IoVec::from_raw_parts(ptr::null_mut(), 0));
-        self.is_owned.push(false);
-        self
-    }
-
-    /// Add a mount option that does not take a value, but whose name must be
-    /// owned.
-    ///
-    ///
-    /// This has higher runtime cost than [`Nmount::null_opt`], but is useful
-    /// when the name's lifetime doesn't outlive the `Nmount`, or it's a
-    /// different string type than `CStr`.
-    ///
-    /// # Examples
-    /// ```
-    /// use nix::mount::Nmount;
-    ///
-    /// let read_only = "ro";
-    /// let mut nmount: Nmount<'static> = Nmount::new();
-    /// nmount.null_opt_owned(read_only);
-    /// ```
-    pub fn null_opt_owned<P: ?Sized + NixPath>(&mut self, name: &P) -> &mut Self
-    {
-        name.with_nix_path(|s| {
-            let len = s.to_bytes_with_nul().len();
-            self.iov.push(IoVec::from_raw_parts(
-                // Must free it later
-                s.to_owned().into_raw() as *mut c_void,
-                len
-            ));
-            self.is_owned.push(true);
-        }).unwrap();
-        self.iov.push(IoVec::from_raw_parts(ptr::null_mut(), 0));
-        self.is_owned.push(false);
-        self
-    }
-
-    /// Add a mount option as a [`CStr`].
-    ///
-    /// # Examples
-    /// ```
-    /// use nix::mount::Nmount;
-    /// use std::ffi::CString;
-    ///
-    /// let fstype = CString::new("fstype").unwrap();
-    /// let nullfs = CString::new("nullfs").unwrap();
-    /// Nmount::new()
-    ///     .str_opt(&fstype, &nullfs);
-    /// ```
-    pub fn str_opt(
-        &mut self,
-        name: &'a CStr,
-        val: &'a CStr
-    ) -> &mut Self
-    {
-        self.iov.push(IoVec::from_slice(name.to_bytes_with_nul()));
-        self.is_owned.push(false);
-        self.iov.push(IoVec::from_slice(val.to_bytes_with_nul()));
-        self.is_owned.push(false);
-        self
-    }
-
-    /// Add a mount option as an owned string.
-    ///
-    /// This has higher runtime cost than [`Nmount::str_opt`], but is useful
-    /// when the value's lifetime doesn't outlive the `Nmount`, or it's a
-    /// different string type than `CStr`.
-    ///
-    /// # Examples
-    /// ```
-    /// use nix::mount::Nmount;
-    /// use std::path::Path;
-    ///
-    /// let mountpoint = Path::new("/mnt");
-    /// Nmount::new()
-    ///     .str_opt_owned("fspath", mountpoint.to_str().unwrap());
-    /// ```
-    pub fn str_opt_owned<P1, P2>(&mut self, name: &P1, val: &P2) -> &mut Self
-        where P1: ?Sized + NixPath,
-              P2: ?Sized + NixPath
-    {
-        name.with_nix_path(|s| {
-            let len = s.to_bytes_with_nul().len();
-            self.iov.push(IoVec::from_raw_parts(
-                // Must free it later
-                s.to_owned().into_raw() as *mut c_void,
-                len
-            ));
-            self.is_owned.push(true);
-        }).unwrap();
-        val.with_nix_path(|s| {
-            let len = s.to_bytes_with_nul().len();
-            self.iov.push(IoVec::from_raw_parts(
-                // Must free it later
-                s.to_owned().into_raw() as *mut c_void,
-                len
-            ));
-            self.is_owned.push(true);
-        }).unwrap();
-        self
-    }
-
-    /// Create a new `Nmount` struct with no options
-    pub fn new() -> Self {
-        Self::default()
-    }
-
-    /// Actually mount the file system.
-    pub fn nmount(&mut self, flags: MntFlags) -> NmountResult {
-        // nmount can return extra error information via a "errmsg" return
-        // argument.
-        const ERRMSG_NAME: &[u8] = b"errmsg\0";
-        let mut errmsg = vec![0u8; 255];
-        self.iov.push(IoVec::from_raw_parts(
-                ERRMSG_NAME.as_ptr() as *mut c_void,
-                ERRMSG_NAME.len()
-        ));
-        self.iov.push(IoVec::from_raw_parts(
-                errmsg.as_mut_ptr() as *mut c_void,
-                errmsg.len()
-        ));
-
-        let niov = self.iov.len() as c_uint;
-        let iovp = self.iov.as_mut_ptr() as *mut libc::iovec;
-        let res = unsafe {
-            libc::nmount(iovp, niov, flags.bits)
-        };
-        match Errno::result(res) {
-            Ok(_) => Ok(()),
-            Err(error) => {
-                let errmsg = match errmsg.iter().position(|&x| x == 0) {
-                    None => None,
-                    Some(0) => None,
-                    Some(n) => {
-                        let sl = &errmsg[0..n + 1];
-                        Some(CStr::from_bytes_with_nul(sl).unwrap())
-                    }
-                };
-                Err(NmountError::new(error, errmsg))
-            }
-        }
-    }
-}
-
-#[cfg(target_os = "freebsd")]
-impl<'a> Drop for Nmount<'a> {
-    fn drop(&mut self) {
-        for (iov, is_owned) in self.iov.iter().zip(self.is_owned.iter()) {
-            if *is_owned {
-                // Free the owned string.  Safe because we recorded ownership,
-                // and Nmount does not implement Clone.
-                unsafe {
-                    drop(CString::from_raw(iov.0.iov_base as *mut c_char));
-                }
-            }
-        }
-    }
-}
-
-/// Unmount the file system mounted at `mountpoint`.
-///
-/// Useful flags include
-/// * `MNT_FORCE` -     Unmount even if still in use.
-/// * `MNT_BYFSID` -    `mountpoint` is not a path, but a file system ID
-///                     encoded as `FSID:val0:val1`, where `val0` and `val1`
-///                     are the contents of the `fsid_t val[]` array in decimal.
-///                     The file system that has the specified file system ID
-///                     will be unmounted.  See
-///                     [`statfs`](crate::sys::statfs::statfs) to determine the
-///                     `fsid`.
-pub fn unmount<P>(mountpoint: &P, flags: MntFlags) -> Result<()>
-    where P: ?Sized + NixPath
-{
-    let res = mountpoint.with_nix_path(|cstr| {
-        unsafe { libc::unmount(cstr.as_ptr(), flags.bits) }
-    })?;
-
-    Errno::result(res).map(drop)
-}
diff --git a/src/mount/mod.rs b/src/mount/mod.rs
deleted file mode 100644
index 14bf2a9..0000000
--- a/src/mount/mod.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//! Mount file systems
-#[cfg(any(target_os = "android", target_os = "linux"))]
-mod linux;
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::linux::*;
-
-#[cfg(any(target_os = "dragonfly",
-          target_os = "freebsd",
-          target_os = "macos",
-          target_os = "netbsd",
-          target_os = "openbsd"))]
-mod bsd;
-
-#[cfg(any(target_os = "dragonfly",
-          target_os = "freebsd",
-          target_os = "macos",
-          target_os = "netbsd",
-          target_os = "openbsd"
-          ))]
-pub use self::bsd::*;
diff --git a/src/mqueue.rs b/src/mqueue.rs
index 34fd802..0215de5 100644
--- a/src/mqueue.rs
+++ b/src/mqueue.rs
@@ -1,6 +1,6 @@
 //! Posix Message Queue functions
 //!
-//! [Further reading and details on the C API](https://man7.org/linux/man-pages/man7/mq_overview.7.html)
+//! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html)
 
 use crate::Result;
 use crate::errno::Errno;
@@ -59,7 +59,7 @@
         }
     }
 
-    pub const fn flags(&self) -> mq_attr_member_t {
+    pub fn flags(&self) -> mq_attr_member_t {
         self.mq_attr.mq_flags
     }
 }
@@ -67,7 +67,7 @@
 
 /// Open a message queue
 ///
-/// See also [`mq_open(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
+/// See also [`mq_open(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
 // The mode.bits cast is only lossless on some OSes
 #[allow(clippy::cast_lossless)]
 pub fn mq_open(name: &CString,
@@ -89,7 +89,7 @@
 
 /// Remove a message queue
 ///
-/// See also [`mq_unlink(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html)
+/// See also [`mq_unlink(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html)
 pub fn mq_unlink(name: &CString) -> Result<()> {
     let res = unsafe { libc::mq_unlink(name.as_ptr()) };
     Errno::result(res).map(drop)
@@ -97,7 +97,7 @@
 
 /// Close a message queue
 ///
-/// See also [`mq_close(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html)
+/// See also [`mq_close(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html)
 pub fn mq_close(mqdes: mqd_t) -> Result<()> {
     let res = unsafe { libc::mq_close(mqdes) };
     Errno::result(res).map(drop)
@@ -105,7 +105,7 @@
 
 /// Receive a message from a message queue
 ///
-/// See also [`mq_receive(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html)
+/// See also [`mq_receive(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html)
 pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> {
     let len = message.len() as size_t;
     let res = unsafe {
@@ -119,7 +119,7 @@
 
 /// Send a message to a message queue
 ///
-/// See also [`mq_send(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
+/// See also [`mq_send(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
 pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
     let res = unsafe {
         libc::mq_send(mqdes,
@@ -132,7 +132,7 @@
 
 /// Get message queue attributes
 ///
-/// See also [`mq_getattr(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html)
+/// See also [`mq_getattr(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html)
 pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
     let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
     let res = unsafe { libc::mq_getattr(mqd, attr.as_mut_ptr()) };
@@ -143,7 +143,7 @@
 /// Returns the old attributes
 /// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html)
 pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
     let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
     let res = unsafe {
@@ -155,7 +155,6 @@
 /// Convenience function.
 /// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
 /// Returns the old attributes
-#[allow(clippy::useless_conversion)]    // Not useless on all OSes
 pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> {
     let oldattr = mq_getattr(mqd)?;
     let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
diff --git a/src/net/if_.rs b/src/net/if_.rs
index bc00a43..9636488 100644
--- a/src/net/if_.rs
+++ b/src/net/if_.rs
@@ -3,8 +3,8 @@
 //! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
 //! or "socan1" into device numbers.
 
-use crate::{Error, NixPath, Result};
 use libc::c_uint;
+use crate::{Result, Error, NixPath};
 
 /// Resolve an interface into a interface number.
 pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
@@ -21,41 +21,39 @@
     /// Standard interface flags, used by `getifaddrs`
     pub struct InterfaceFlags: libc::c_int {
         /// Interface is running. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_UP;
         /// Valid broadcast address set. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_BROADCAST;
         /// Internal debugging flag. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_DEBUG;
         /// Interface is a loopback interface. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_LOOPBACK;
         /// Interface is a point-to-point link. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_POINTOPOINT;
         /// Avoid use of trailers. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         #[cfg(any(target_os = "android",
                   target_os = "fuchsia",
                   target_os = "ios",
                   target_os = "linux",
                   target_os = "macos",
                   target_os = "netbsd",
-                  target_os = "illumos",
                   target_os = "solaris"))]
         IFF_NOTRAILERS;
         /// Interface manages own routes.
         #[cfg(any(target_os = "dragonfly"))]
         IFF_SMART;
         /// Resources allocated. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         #[cfg(any(target_os = "android",
                   target_os = "dragonfly",
                   target_os = "freebsd",
                   target_os = "fuchsia",
-                  target_os = "illumos",
                   target_os = "ios",
                   target_os = "linux",
                   target_os = "macos",
@@ -64,16 +62,16 @@
                   target_os = "solaris"))]
         IFF_RUNNING;
         /// No arp protocol, L2 destination address not set. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_NOARP;
         /// Interface is in promiscuous mode. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_PROMISC;
         /// Receive all multicast packets. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_ALLMULTI;
         /// Master of a load balancing bundle. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
         IFF_MASTER;
         /// transmission in progress, tx hardware queue is full
@@ -84,10 +82,10 @@
                   target_os = "ios"))]
         IFF_OACTIVE;
         /// Protocol code on board.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(target_os = "solaris")]
         IFF_INTELLIGENT;
         /// Slave of a load balancing bundle. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
         IFF_SLAVE;
         /// Can't hear own transmissions.
@@ -99,7 +97,7 @@
                   target_os = "osx"))]
         IFF_SIMPLEX;
         /// Supports multicast. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_MULTICAST;
         /// Per link layer defined bit.
         #[cfg(any(target_os = "dragonfly",
@@ -110,10 +108,10 @@
                   target_os = "ios"))]
         IFF_LINK0;
         /// Multicast using broadcast.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_MULTI_BCAST;
         /// Is able to select media type via ifmap. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
         IFF_PORTSEL;
         /// Per link layer defined bit.
@@ -125,10 +123,10 @@
                   target_os = "ios"))]
         IFF_LINK1;
         /// Non-unique address.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_UNNUMBERED;
         /// Auto media selection active. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
         IFF_AUTOMEDIA;
         /// Per link layer defined bit.
@@ -145,15 +143,15 @@
                   target_os = "macos",
                   target_os = "ios"))]
         IFF_ALTPHYS;
-        /// DHCP controls interface.
-        #[cfg(any(target_os = "solaris", target_os = "illumos"))]
+        /// DHCP controlls interface.
+        #[cfg(any(target_os = "solaris"))]
         IFF_DHCPRUNNING;
         /// The addresses are lost when the interface goes down. (see
-        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
         #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
         IFF_DYNAMIC;
         /// Do not advertise.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_PRIVATE;
         /// Driver signals L1 up. Volatile.
         #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
@@ -165,7 +163,7 @@
         #[cfg(any(target_os = "freebsd"))]
         IFF_CANTCONFIG;
         /// Do not transmit packets.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_NOXMIT;
         /// Driver signals dormant. Volatile.
         #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
@@ -174,7 +172,7 @@
         #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
         IFF_PPROMISC;
         /// Just on-link subnet.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_NOLOCAL;
         /// Echo sent packets. Volatile.
         #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
@@ -183,19 +181,19 @@
         #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
         IFF_MONITOR;
         /// Address is deprecated.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_DEPRECATED;
         /// Static ARP.
         #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
         IFF_STATICARP;
         /// Address from stateless addrconf.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_ADDRCONF;
         /// Interface is in polling mode.
         #[cfg(any(target_os = "dragonfly"))]
         IFF_NPOLLING;
         /// Router on interface.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_ROUTER;
         /// Interface is in polling mode.
         #[cfg(any(target_os = "dragonfly"))]
@@ -204,208 +202,66 @@
         #[cfg(any(target_os = "freebsd"))]
         IFF_DYING;
         /// No NUD on interface.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_NONUD;
         /// Interface is being renamed
         #[cfg(any(target_os = "freebsd"))]
         IFF_RENAMING;
         /// Anycast address.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_ANYCAST;
         /// Don't exchange routing info.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_NORTEXCH;
         /// Do not provide packet information
         #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
         IFF_NO_PI as libc::c_int;
-        /// TUN device (no Ethernet headers)
+        /// TUN device (no Ethernet headers) 
         #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
         IFF_TUN as libc::c_int;
         /// TAP device
         #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
         IFF_TAP as libc::c_int;
         /// IPv4 interface.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_IPV4;
         /// IPv6 interface.
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_IPV6;
         /// in.mpathd test address
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_NOFAILOVER;
         /// Interface has failed
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_FAILED;
         /// Interface is a hot-spare
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_STANDBY;
         /// Functioning but not used
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_INACTIVE;
         /// Interface is offline
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        #[cfg(any(target_os = "solaris"))]
         IFF_OFFLINE;
-        #[cfg(target_os = "solaris")]
+        #[cfg(any(target_os = "solaris"))]
         IFF_COS_ENABLED;
         /// Prefer as source addr.
-        #[cfg(target_os = "solaris")]
+        #[cfg(any(target_os = "solaris"))]
         IFF_PREFERRED;
         /// RFC3041
-        #[cfg(target_os = "solaris")]
+        #[cfg(any(target_os = "solaris"))]
         IFF_TEMPORARY;
         /// MTU set with SIOCSLIFMTU
-        #[cfg(target_os = "solaris")]
+        #[cfg(any(target_os = "solaris"))]
         IFF_FIXEDMTU;
         /// Cannot send / receive packets
-        #[cfg(target_os = "solaris")]
+        #[cfg(any(target_os = "solaris"))]
         IFF_VIRTUAL;
         /// Local address in use
-        #[cfg(target_os = "solaris")]
+        #[cfg(any(target_os = "solaris"))]
         IFF_DUPLICATE;
         /// IPMP IP interface
-        #[cfg(target_os = "solaris")]
+        #[cfg(any(target_os = "solaris"))]
         IFF_IPMP;
     }
 );
-
-#[cfg(any(
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "fuchsia",
-    target_os = "ios",
-    target_os = "linux",
-    target_os = "macos",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
-mod if_nameindex {
-    use super::*;
-
-    use std::ffi::CStr;
-    use std::fmt;
-    use std::marker::PhantomData;
-    use std::ptr::NonNull;
-
-    /// A network interface. Has a name like "eth0" or "wlp4s0" or "wlan0", as well as an index
-    /// (1, 2, 3, etc) that identifies it in the OS's networking stack.
-    #[allow(missing_copy_implementations)]
-    #[repr(transparent)]
-    pub struct Interface(libc::if_nameindex);
-
-    impl Interface {
-        /// Obtain the index of this interface.
-        pub fn index(&self) -> c_uint {
-            self.0.if_index
-        }
-
-        /// Obtain the name of this interface.
-        pub fn name(&self) -> &CStr {
-            unsafe { CStr::from_ptr(self.0.if_name) }
-        }
-    }
-
-    impl fmt::Debug for Interface {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            f.debug_struct("Interface")
-                .field("index", &self.index())
-                .field("name", &self.name())
-                .finish()
-        }
-    }
-
-    /// A list of the network interfaces available on this system. Obtained from [`if_nameindex()`].
-    pub struct Interfaces {
-        ptr: NonNull<libc::if_nameindex>,
-    }
-
-    impl Interfaces {
-        /// Iterate over the interfaces in this list.
-        #[inline]
-        pub fn iter(&self) -> InterfacesIter<'_> {
-            self.into_iter()
-        }
-
-        /// Convert this to a slice of interfaces. Note that the underlying interfaces list is
-        /// null-terminated, so calling this calculates the length. If random access isn't needed,
-        /// [`Interfaces::iter()`] should be used instead.
-        pub fn to_slice(&self) -> &[Interface] {
-            let ifs = self.ptr.as_ptr() as *const Interface;
-            let len = self.iter().count();
-            unsafe { std::slice::from_raw_parts(ifs, len) }
-        }
-    }
-
-    impl Drop for Interfaces {
-        fn drop(&mut self) {
-            unsafe { libc::if_freenameindex(self.ptr.as_ptr()) };
-        }
-    }
-
-    impl fmt::Debug for Interfaces {
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            self.to_slice().fmt(f)
-        }
-    }
-
-    impl<'a> IntoIterator for &'a Interfaces {
-        type IntoIter = InterfacesIter<'a>;
-        type Item = &'a Interface;
-        #[inline]
-        fn into_iter(self) -> Self::IntoIter {
-            InterfacesIter {
-                ptr: self.ptr.as_ptr(),
-                _marker: PhantomData,
-            }
-        }
-    }
-
-    /// An iterator over the interfaces in an [`Interfaces`].
-    #[derive(Debug)]
-    pub struct InterfacesIter<'a> {
-        ptr: *const libc::if_nameindex,
-        _marker: PhantomData<&'a Interfaces>,
-    }
-
-    impl<'a> Iterator for InterfacesIter<'a> {
-        type Item = &'a Interface;
-        #[inline]
-        fn next(&mut self) -> Option<Self::Item> {
-            unsafe {
-                if (*self.ptr).if_index == 0 {
-                    None
-                } else {
-                    let ret = &*(self.ptr as *const Interface);
-                    self.ptr = self.ptr.add(1);
-                    Some(ret)
-                }
-            }
-        }
-    }
-
-    /// Retrieve a list of the network interfaces available on the local system.
-    ///
-    /// ```
-    /// let interfaces = nix::net::if_::if_nameindex().unwrap();
-    /// for iface in &interfaces {
-    ///     println!("Interface #{} is called {}", iface.index(), iface.name().to_string_lossy());
-    /// }
-    /// ```
-    pub fn if_nameindex() -> Result<Interfaces> {
-        unsafe {
-            let ifs = libc::if_nameindex();
-            let ptr = NonNull::new(ifs).ok_or_else(Error::last)?;
-            Ok(Interfaces { ptr })
-        }
-    }
-}
-#[cfg(any(
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "fuchsia",
-    target_os = "ios",
-    target_os = "linux",
-    target_os = "macos",
-    target_os = "netbsd",
-    target_os = "openbsd",
-))]
-pub use if_nameindex::*;
diff --git a/src/poll.rs b/src/poll.rs
index 8556c1b..be5bf22 100644
--- a/src/poll.rs
+++ b/src/poll.rs
@@ -3,7 +3,7 @@
 use crate::sys::time::TimeSpec;
 #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
 use crate::sys::signal::SigSet;
-use std::os::unix::io::{AsRawFd, RawFd};
+use std::os::unix::io::RawFd;
 
 use crate::Result;
 use crate::errno::Errno;
@@ -25,7 +25,7 @@
 impl PollFd {
     /// Creates a new `PollFd` specifying the events of interest
     /// for a given file descriptor.
-    pub const fn new(fd: RawFd, events: PollFlags) -> PollFd {
+    pub fn new(fd: RawFd, events: PollFlags) -> PollFd {
         PollFd {
             pollfd: libc::pollfd {
                 fd,
@@ -35,27 +35,10 @@
         }
     }
 
-    /// Returns the events that occured in the last call to `poll` or `ppoll`.  Will only return
-    /// `None` if the kernel provides status flags that Nix does not know about.
+    /// Returns the events that occured in the last call to `poll` or `ppoll`.
     pub fn revents(self) -> Option<PollFlags> {
         PollFlags::from_bits(self.pollfd.revents)
     }
-
-    /// The events of interest for this `PollFd`.
-    pub fn events(self) -> PollFlags {
-        PollFlags::from_bits(self.pollfd.events).unwrap()
-    }
-
-    /// Modify the events of interest for this `PollFd`.
-    pub fn set_events(&mut self, events: PollFlags) {
-        self.pollfd.events = events.bits();
-    }
-}
-
-impl AsRawFd for PollFd {
-    fn as_raw_fd(&self) -> RawFd {
-        self.pollfd.fd
-    }
 }
 
 libc_bitflags! {
@@ -68,12 +51,12 @@
         /// Possibilities include:
         ///
         /// *  There is out-of-band data on a TCP socket (see
-        ///    [tcp(7)](https://man7.org/linux/man-pages/man7/tcp.7.html)).
+        ///    [tcp(7)](http://man7.org/linux/man-pages/man7/tcp.7.html)).
         /// *  A pseudoterminal master in packet mode has seen a state
         ///    change on the slave (see
-        ///    [ioctl_tty(2)](https://man7.org/linux/man-pages/man2/ioctl_tty.2.html)).
+        ///    [ioctl_tty(2)](http://man7.org/linux/man-pages/man2/ioctl_tty.2.html)).
         /// *  A cgroup.events file has been modified (see
-        ///    [cgroups(7)](https://man7.org/linux/man-pages/man7/cgroups.7.html)).
+        ///    [cgroups(7)](http://man7.org/linux/man-pages/man7/cgroups.7.html)).
         POLLPRI;
         /// Writing is now possible, though a write larger that the
         /// available space in a socket or pipe will still block (unless
@@ -113,7 +96,7 @@
 }
 
 /// `poll` waits for one of a set of file descriptors to become ready to perform I/O.
-/// ([`poll(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html))
+/// ([`poll(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html))
 ///
 /// `fds` contains all [`PollFd`](struct.PollFd.html) to poll.
 /// The function will return as soon as any event occur for any of these `PollFd`s.
@@ -144,7 +127,7 @@
 
 /// `ppoll()` allows an application to safely wait until either a file
 /// descriptor becomes ready or until a signal is caught.
-/// ([`poll(2)`](https://man7.org/linux/man-pages/man2/poll.2.html))
+/// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html))
 ///
 /// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it
 /// with the `sigmask` argument. If you want `ppoll` to block indefinitely,
diff --git a/src/pty.rs b/src/pty.rs
index facc9aa..d67518f 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -10,7 +10,7 @@
 
 use crate::sys::termios::Termios;
 use crate::unistd::{self, ForkResult, Pid};
-use crate::{Result, fcntl};
+use crate::{Result, Error, fcntl};
 use crate::errno::Errno;
 
 /// Representation of a master/slave pty pair
@@ -70,7 +70,7 @@
         // condition, which can cause confusing errors for future I/O
         // operations.
         let e = unistd::close(self.0);
-        if e == Err(Errno::EBADF) {
+        if e == Err(Error::Sys(Errno::EBADF)) {
             panic!("Closing an invalid file descriptor!");
         };
     }
@@ -78,13 +78,13 @@
 
 impl io::Read for PtyMaster {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        unistd::read(self.0, buf).map_err(io::Error::from)
+        unistd::read(self.0, buf).map_err(|e| e.as_errno().unwrap().into())
     }
 }
 
 impl io::Write for PtyMaster {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        unistd::write(self.0, buf).map_err(io::Error::from)
+        unistd::write(self.0, buf).map_err(|e| e.as_errno().unwrap().into())
     }
     fn flush(&mut self) -> io::Result<()> {
         Ok(())
@@ -92,21 +92,21 @@
 }
 
 /// Grant access to a slave pseudoterminal (see
-/// [`grantpt(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
+/// [`grantpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
 ///
 /// `grantpt()` changes the mode and owner of the slave pseudoterminal device corresponding to the
 /// master pseudoterminal referred to by `fd`. This is a necessary step towards opening the slave.
 #[inline]
 pub fn grantpt(fd: &PtyMaster) -> Result<()> {
     if unsafe { libc::grantpt(fd.as_raw_fd()) } < 0 {
-        return Err(Errno::last());
+        return Err(Error::last());
     }
 
     Ok(())
 }
 
 /// Open a pseudoterminal device (see
-/// [`posix_openpt(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html))
+/// [`posix_openpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html))
 ///
 /// `posix_openpt()` returns a file descriptor to an existing unused pseuterminal master device.
 ///
@@ -145,14 +145,14 @@
     };
 
     if fd < 0 {
-        return Err(Errno::last());
+        return Err(Error::last());
     }
 
     Ok(PtyMaster(fd))
 }
 
 /// Get the name of the slave pseudoterminal (see
-/// [`ptsname(3)`](https://man7.org/linux/man-pages/man3/ptsname.3.html))
+/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
 ///
 /// `ptsname()` returns the name of the slave pseudoterminal device corresponding to the master
 /// referred to by `fd`.
@@ -171,7 +171,7 @@
 pub unsafe fn ptsname(fd: &PtyMaster) -> Result<String> {
     let name_ptr = libc::ptsname(fd.as_raw_fd());
     if name_ptr.is_null() {
-        return Err(Errno::last());
+        return Err(Error::last());
     }
 
     let name = CStr::from_ptr(name_ptr);
@@ -179,7 +179,7 @@
 }
 
 /// Get the name of the slave pseudoterminal (see
-/// [`ptsname(3)`](https://man7.org/linux/man-pages/man3/ptsname.3.html))
+/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
 ///
 /// `ptsname_r()` returns the name of the slave pseudoterminal device corresponding to the master
 /// referred to by `fd`. This is the threadsafe version of `ptsname()`, but it is not part of the
@@ -190,22 +190,23 @@
 #[cfg(any(target_os = "android", target_os = "linux"))]
 #[inline]
 pub fn ptsname_r(fd: &PtyMaster) -> Result<String> {
-    let mut name_buf = Vec::<libc::c_char>::with_capacity(64);
-    let name_buf_ptr = name_buf.as_mut_ptr();
-    let cname = unsafe {
-        let cap = name_buf.capacity();
-        if libc::ptsname_r(fd.as_raw_fd(), name_buf_ptr, cap) != 0 {
-            return Err(crate::Error::last());
-        }
-        CStr::from_ptr(name_buf.as_ptr())
-    };
+    let mut name_buf = vec![0u8; 64];
+    let name_buf_ptr = name_buf.as_mut_ptr() as *mut libc::c_char;
+    if unsafe { libc::ptsname_r(fd.as_raw_fd(), name_buf_ptr, name_buf.capacity()) } != 0 {
+        return Err(Error::last());
+    }
 
-    let name = cname.to_string_lossy().into_owned();
+    // Find the first null-character terminating this string. This is guaranteed to succeed if the
+    // return value of `libc::ptsname_r` is 0.
+    let null_index = name_buf.iter().position(|c| *c == b'\0').unwrap();
+    name_buf.truncate(null_index);
+
+    let name = String::from_utf8(name_buf)?;
     Ok(name)
 }
 
 /// Unlock a pseudoterminal master/slave pseudoterminal pair (see
-/// [`unlockpt(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html))
+/// [`unlockpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html))
 ///
 /// `unlockpt()` unlocks the slave pseudoterminal device corresponding to the master pseudoterminal
 /// referred to by `fd`. This must be called before trying to open the slave side of a
@@ -213,7 +214,7 @@
 #[inline]
 pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
     if unsafe { libc::unlockpt(fd.as_raw_fd()) } < 0 {
-        return Err(Errno::last());
+        return Err(Error::last());
     }
 
     Ok(())
@@ -222,7 +223,7 @@
 
 /// Create a new pseudoterminal, returning the slave and master file descriptors
 /// in `OpenptyResult`
-/// (see [`openpty`](https://man7.org/linux/man-pages/man3/openpty.3.html)).
+/// (see [`openpty`](http://man7.org/linux/man-pages/man3/openpty.3.html)).
 ///
 /// If `winsize` is not `None`, the window size of the slave will be set to
 /// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
@@ -296,24 +297,12 @@
 
 /// Create a new pseudoterminal, returning the master file descriptor and forked pid.
 /// in `ForkptyResult`
-/// (see [`forkpty`](https://man7.org/linux/man-pages/man3/forkpty.3.html)).
+/// (see [`forkpty`](http://man7.org/linux/man-pages/man3/forkpty.3.html)).
 ///
 /// If `winsize` is not `None`, the window size of the slave will be set to
 /// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's
 /// terminal settings of the slave will be set to the values in `termios`.
-///
-/// # Safety
-///
-/// In a multithreaded program, only [async-signal-safe] functions like `pause`
-/// and `_exit` may be called by the child (the parent isn't restricted). Note
-/// that memory allocation may **not** be async-signal-safe and thus must be
-/// prevented.
-///
-/// Those functions are only a small subset of your operating system's API, so
-/// special care must be taken to only invoke code you can control and audit.
-///
-/// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html
-pub unsafe fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(
+pub fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(
     winsize: T,
     termios: U,
 ) -> Result<ForkptyResult> {
@@ -334,15 +323,20 @@
         .map(|ws| ws as *const Winsize as *mut _)
         .unwrap_or(ptr::null_mut());
 
-    let res = libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win);
+    let res = unsafe {
+        libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win)
+    };
 
     let fork_result = Errno::result(res).map(|res| match res {
         0 => ForkResult::Child,
         res => ForkResult::Parent { child: Pid::from_raw(res) },
     })?;
 
-    Ok(ForkptyResult {
-        master: master.assume_init(),
-        fork_result,
-    })
+    unsafe {
+        Ok(ForkptyResult {
+            master: master.assume_init(),
+            fork_result,
+        })
+    }
 }
+
diff --git a/src/sched.rs b/src/sched.rs
index c2dd7b8..3b48b4a 100644
--- a/src/sched.rs
+++ b/src/sched.rs
@@ -1,7 +1,3 @@
-//! Execution scheduling
-//!
-//! See Also
-//! [sched.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sched.h.html)
 use crate::{Errno, Result};
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
@@ -15,75 +11,38 @@
     use std::option::Option;
     use std::os::unix::io::RawFd;
     use crate::unistd::Pid;
-    use crate::Result;
+    use crate::{Error, Result};
 
     // For some functions taking with a parameter of type CloneFlags,
     // only a subset of these flags have an effect.
     libc_bitflags! {
-        /// Options for use with [`clone`]
         pub struct CloneFlags: c_int {
-            /// The calling process and the child process run in the same
-            /// memory space.
             CLONE_VM;
-            /// The caller and the child process share the same  filesystem
-            /// information.
             CLONE_FS;
-            /// The calling process and the child process share the same file
-            /// descriptor table.
             CLONE_FILES;
-            /// The calling process and the child process share the same table
-            /// of signal handlers.
             CLONE_SIGHAND;
-            /// If the calling process is being traced, then trace the child
-            /// also.
             CLONE_PTRACE;
-            /// The execution of the calling process is suspended until the
-            /// child releases its virtual memory resources via a call to
-            /// execve(2) or _exit(2) (as with vfork(2)).
             CLONE_VFORK;
-            /// The parent of the new child  (as returned by getppid(2))
-            /// will be the same as that of the calling process.
             CLONE_PARENT;
-            /// The child is placed in the same thread group as the calling
-            /// process.
             CLONE_THREAD;
-            /// The cloned child is started in a new mount namespace.
             CLONE_NEWNS;
-            /// The child and the calling process share a single list of System
-            /// V semaphore adjustment values
             CLONE_SYSVSEM;
-            // Not supported by Nix due to lack of varargs support in Rust FFI
-            // CLONE_SETTLS;
-            // Not supported by Nix due to lack of varargs support in Rust FFI
-            // CLONE_PARENT_SETTID;
-            // Not supported by Nix due to lack of varargs support in Rust FFI
-            // CLONE_CHILD_CLEARTID;
-            /// Unused since Linux 2.6.2
-            #[deprecated(since = "0.23.0", note = "Deprecated by Linux 2.6.2")]
+            CLONE_SETTLS;
+            CLONE_PARENT_SETTID;
+            CLONE_CHILD_CLEARTID;
             CLONE_DETACHED;
-            /// A tracing process cannot force `CLONE_PTRACE` on this child
-            /// process.
             CLONE_UNTRACED;
-            // Not supported by Nix due to lack of varargs support in Rust FFI
-            // CLONE_CHILD_SETTID;
-            /// Create the process in a new cgroup namespace.
+            CLONE_CHILD_SETTID;
             CLONE_NEWCGROUP;
-            /// Create the process in a new UTS namespace.
             CLONE_NEWUTS;
-            /// Create the process in a new IPC namespace.
             CLONE_NEWIPC;
-            /// Create the process in a new user namespace.
             CLONE_NEWUSER;
-            /// Create the process in a new PID namespace.
             CLONE_NEWPID;
-            /// Create the process in a new network namespace.
             CLONE_NEWNET;
-            /// The new process shares an I/O context with the calling process.
             CLONE_IO;
         }
     }
 
-    /// Type for the function executed by [`clone`].
     pub type CloneCb<'a> = Box<dyn FnMut() -> isize + 'a>;
 
     /// CpuSet represent a bit-mask of CPUs.
@@ -109,7 +68,7 @@
         /// `field` is the CPU id to test
         pub fn is_set(&self, field: usize) -> Result<bool> {
             if field >= CpuSet::count() {
-                Err(Errno::EINVAL)
+                Err(Error::Sys(Errno::EINVAL))
             } else {
                 Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
             }
@@ -119,7 +78,7 @@
         /// `field` is the CPU id to add
         pub fn set(&mut self, field: usize) -> Result<()> {
             if field >= CpuSet::count() {
-                Err(Errno::EINVAL)
+                Err(Error::Sys(Errno::EINVAL))
             } else {
                 unsafe { libc::CPU_SET(field, &mut self.cpu_set); }
                 Ok(())
@@ -130,7 +89,7 @@
         /// `field` is the CPU id to remove
         pub fn unset(&mut self, field: usize) -> Result<()> {
             if field >= CpuSet::count() {
-                Err(Errno::EINVAL)
+                Err(Error::Sys(Errno::EINVAL))
             } else {
                 unsafe { libc::CPU_CLR(field, &mut self.cpu_set);}
                 Ok(())
@@ -138,7 +97,7 @@
         }
 
         /// Return the maximum number of CPU in CpuSet
-        pub const fn count() -> usize {
+        pub fn count() -> usize {
             8 * mem::size_of::<libc::cpu_set_t>()
         }
     }
@@ -150,7 +109,7 @@
     }
 
     /// `sched_setaffinity` set a thread's CPU affinity mask
-    /// ([`sched_setaffinity(2)`](https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html))
+    /// ([`sched_setaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html))
     ///
     /// `pid` is the thread ID to update.
     /// If pid is zero, then the calling thread is updated.
@@ -183,7 +142,7 @@
     }
 
     /// `sched_getaffinity` get a thread's CPU affinity mask
-    /// ([`sched_getaffinity(2)`](https://man7.org/linux/man-pages/man2/sched_getaffinity.2.html))
+    /// ([`sched_getaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_getaffinity.2.html))
     ///
     /// `pid` is the thread ID to check.
     /// If pid is zero, then the calling thread is checked.
@@ -217,14 +176,6 @@
         Errno::result(res).and(Ok(cpuset))
     }
 
-    /// `clone` create a child process
-    /// ([`clone(2)`](https://man7.org/linux/man-pages/man2/clone.2.html))
-    ///
-    /// `stack` is a reference to an array which will hold the stack of the new
-    /// process.  Unlike when calling `clone(2)` from C, the provided stack
-    /// address need not be the highest address of the region.  Nix will take
-    /// care of that requirement.  The user only needs to provide a reference to
-    /// a normally allocated buffer.
     pub fn clone(
         mut cb: CloneCb,
         stack: &mut [u8],
@@ -253,18 +204,12 @@
         Errno::result(res).map(Pid::from_raw)
     }
 
-    /// disassociate parts of the process execution context
-    ///
-    /// See also [unshare(2)](https://man7.org/linux/man-pages/man2/unshare.2.html)
     pub fn unshare(flags: CloneFlags) -> Result<()> {
         let res = unsafe { libc::unshare(flags.bits()) };
 
         Errno::result(res).map(drop)
     }
 
-    /// reassociate thread with a namespace
-    ///
-    /// See also [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html)
     pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
         let res = unsafe { libc::setns(fd, nstype.bits()) };
 
@@ -274,7 +219,7 @@
 
 /// Explicitly yield the processor to other threads.
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html)
 pub fn sched_yield() -> Result<()> {
     let res = unsafe { libc::sched_yield() };
 
diff --git a/src/sys/aio.rs b/src/sys/aio.rs
index e64a2a8..1afdb35 100644
--- a/src/sys/aio.rs
+++ b/src/sys/aio.rs
@@ -21,15 +21,15 @@
 //! [`aio_cancel_all`](fn.aio_cancel_all.html), though the operating system may
 //! not support this for all filesystems and devices.
 
-use crate::Result;
+use crate::{Error, Result};
 use crate::errno::Errno;
 use std::os::unix::io::RawFd;
 use libc::{c_void, off_t, size_t};
+use std::borrow::{Borrow, BorrowMut};
 use std::fmt;
 use std::fmt::Debug;
 use std::marker::PhantomData;
 use std::mem;
-use std::pin::Pin;
 use std::ptr::{null, null_mut};
 use crate::sys::signal::*;
 use std::thread;
@@ -39,7 +39,6 @@
     /// Mode for `AioCb::fsync`.  Controls whether only data or both data and
     /// metadata are synced.
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum AioFsyncMode {
         /// do it like `fsync`
         O_SYNC,
@@ -58,13 +57,9 @@
     /// given `aiocb` should be used for a read operation, a write operation, or
     /// ignored.  Has no effect for any other aio functions.
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum LioOpcode {
-        /// No operation
         LIO_NOP,
-        /// Write data as if by a call to [`AioCb::write`]
         LIO_WRITE,
-        /// Write data as if by a call to [`AioCb::read`]
         LIO_READ,
     }
 }
@@ -95,31 +90,120 @@
     AioAllDone = libc::AIO_ALLDONE,
 }
 
-/// Newtype that adds Send and Sync to libc::aiocb, which contains raw pointers
-#[repr(transparent)]
-struct LibcAiocb(libc::aiocb);
+/// Owns (uniquely or shared) a memory buffer to keep it from `Drop`ing while
+/// the kernel has a pointer to it.
+pub enum Buffer<'a> {
+    /// No buffer to own.
+    ///
+    /// Used for operations like `aio_fsync` that have no data, or for unsafe
+    /// operations that work with raw pointers.
+    None,
+    /// Keeps a reference to a slice
+    Phantom(PhantomData<&'a mut [u8]>),
+    /// Generic thing that keeps a buffer from dropping
+    BoxedSlice(Box<dyn Borrow<[u8]>>),
+    /// Generic thing that keeps a mutable buffer from dropping
+    BoxedMutSlice(Box<dyn BorrowMut<[u8]>>),
+}
 
-unsafe impl Send for LibcAiocb {}
-unsafe impl Sync for LibcAiocb {}
+impl<'a> Debug for Buffer<'a> {
+    // Note: someday it may be possible to Derive Debug for a trait object, but
+    // not today.
+    // https://github.com/rust-lang/rust/issues/1563
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Buffer::None => write!(fmt, "None"),
+            Buffer::Phantom(p) => p.fmt(fmt),
+            Buffer::BoxedSlice(ref bs) => {
+                let borrowed : &dyn Borrow<[u8]> = bs.borrow();
+                write!(fmt, "BoxedSlice({:?})",
+                    borrowed as *const dyn Borrow<[u8]>)
+            },
+            Buffer::BoxedMutSlice(ref bms) => {
+                let borrowed : &dyn BorrowMut<[u8]> = bms.borrow();
+                write!(fmt, "BoxedMutSlice({:?})",
+                    borrowed as *const dyn BorrowMut<[u8]>)
+            }
+        }
+    }
+}
 
 /// AIO Control Block.
 ///
 /// The basic structure used by all aio functions.  Each `AioCb` represents one
 /// I/O request.
 pub struct AioCb<'a> {
-    aiocb: LibcAiocb,
+    aiocb: libc::aiocb,
     /// Tracks whether the buffer pointed to by `libc::aiocb.aio_buf` is mutable
     mutable: bool,
     /// Could this `AioCb` potentially have any in-kernel state?
     in_progress: bool,
-    _buffer: std::marker::PhantomData<&'a [u8]>,
-    _pin: std::marker::PhantomPinned
+    /// Optionally keeps a reference to the data.
+    ///
+    /// Used to keep buffers from `Drop`'ing, and may be returned once the
+    /// `AioCb` is completed by [`buffer`](#method.buffer).
+    buffer: Buffer<'a>
 }
 
 impl<'a> AioCb<'a> {
+    /// Remove the inner `Buffer` and return it
+    ///
+    /// It is an error to call this method while the `AioCb` is still in
+    /// progress.
+    pub fn buffer(&mut self) -> Buffer<'a> {
+        assert!(!self.in_progress);
+        let mut x = Buffer::None;
+        mem::swap(&mut self.buffer, &mut x);
+        x
+    }
+
+    /// Remove the inner boxed slice, if any, and return it.
+    ///
+    /// The returned value will be the argument that was passed to
+    /// `from_boxed_slice` when this `AioCb` was created.
+    ///
+    /// It is an error to call this method while the `AioCb` is still in
+    /// progress.
+    pub fn boxed_slice(&mut self) -> Option<Box<dyn Borrow<[u8]>>> {
+        assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress.  Did you forget to call aio_return?");
+        if let Buffer::BoxedSlice(_) = self.buffer {
+            let mut oldbuffer = Buffer::None;
+            mem::swap(&mut self.buffer, &mut oldbuffer);
+            if let Buffer::BoxedSlice(inner) = oldbuffer {
+                Some(inner)
+            } else {
+                unreachable!();
+            }
+        } else {
+            None
+        }
+    }
+
+    /// Remove the inner boxed mutable slice, if any, and return it.
+    ///
+    /// The returned value will be the argument that was passed to
+    /// `from_boxed_mut_slice` when this `AioCb` was created.
+    ///
+    /// It is an error to call this method while the `AioCb` is still in
+    /// progress.
+    pub fn boxed_mut_slice(&mut self) -> Option<Box<dyn BorrowMut<[u8]>>> {
+        assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress.  Did you forget to call aio_return?");
+        if let Buffer::BoxedMutSlice(_) = self.buffer {
+            let mut oldbuffer = Buffer::None;
+            mem::swap(&mut self.buffer, &mut oldbuffer);
+            if let Buffer::BoxedMutSlice(inner) = oldbuffer {
+                Some(inner)
+            } else {
+                unreachable!();
+            }
+        } else {
+            None
+        }
+    }
+
     /// Returns the underlying file descriptor associated with the `AioCb`
     pub fn fd(&self) -> RawFd {
-        self.aiocb.0.aio_fildes
+        self.aiocb.aio_fildes
     }
 
     /// Constructs a new `AioCb` with no associated buffer.
@@ -148,48 +232,28 @@
     /// # use std::{thread, time};
     /// # use std::os::unix::io::AsRawFd;
     /// # use tempfile::tempfile;
+    /// # fn main() {
     /// let f = tempfile().unwrap();
     /// let mut aiocb = AioCb::from_fd( f.as_raw_fd(), 0, SigevNone);
     /// aiocb.fsync(AioFsyncMode::O_SYNC).expect("aio_fsync failed early");
-    /// while (aiocb.error() == Err(Errno::EINPROGRESS)) {
+    /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
     ///     thread::sleep(time::Duration::from_millis(10));
     /// }
     /// aiocb.aio_return().expect("aio_fsync failed late");
+    /// # }
     /// ```
     pub fn from_fd(fd: RawFd, prio: libc::c_int,
-                    sigev_notify: SigevNotify) -> Pin<Box<AioCb<'a>>> {
+                    sigev_notify: SigevNotify) -> AioCb<'a> {
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        a.0.aio_offset = 0;
-        a.0.aio_nbytes = 0;
-        a.0.aio_buf = null_mut();
-
-        Box::pin(AioCb {
-            aiocb: a,
-            mutable: false,
-            in_progress: false,
-            _buffer: PhantomData,
-            _pin: std::marker::PhantomPinned
-        })
-    }
-
-    // Private helper
-    #[cfg(not(any(target_os = "ios", target_os = "macos")))]
-    fn from_mut_slice_unpinned(fd: RawFd, offs: off_t, buf: &'a mut [u8],
-                          prio: libc::c_int, sigev_notify: SigevNotify,
-                          opcode: LioOpcode) -> AioCb<'a>
-    {
-        let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        a.0.aio_offset = offs;
-        a.0.aio_nbytes = buf.len() as size_t;
-        a.0.aio_buf = buf.as_ptr() as *mut c_void;
-        a.0.aio_lio_opcode = opcode as libc::c_int;
+        a.aio_offset = 0;
+        a.aio_nbytes = 0;
+        a.aio_buf = null_mut();
 
         AioCb {
             aiocb: a,
-            mutable: true,
+            mutable: false,
             in_progress: false,
-            _buffer: PhantomData,
-            _pin: std::marker::PhantomPinned
+            buffer: Buffer::None
         }
     }
 
@@ -198,7 +262,8 @@
     /// The resulting `AioCb` will be suitable for both read and write
     /// operations, but only if the borrow checker can guarantee that the slice
     /// will outlive the `AioCb`.  That will usually be the case if the `AioCb`
-    /// is stack-allocated.
+    /// is stack-allocated.  If the borrow checker gives you trouble, try using
+    /// [`from_boxed_mut_slice`](#method.from_boxed_mut_slice) instead.
     ///
     /// # Parameters
     ///
@@ -227,6 +292,7 @@
     /// # use std::io::Write;
     /// # use std::os::unix::io::AsRawFd;
     /// # use tempfile::tempfile;
+    /// # fn main() {
     /// const INITIAL: &[u8] = b"abcdef123456";
     /// const LEN: usize = 4;
     /// let mut rbuf = vec![0; LEN];
@@ -240,29 +306,220 @@
     ///         SigevNotify::SigevNone,
     ///         LioOpcode::LIO_NOP);
     ///     aiocb.read().unwrap();
-    ///     while (aiocb.error() == Err(Errno::EINPROGRESS)) {
+    ///     while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
     ///         thread::sleep(time::Duration::from_millis(10));
     ///     }
     ///     assert_eq!(aiocb.aio_return().unwrap() as usize, LEN);
     /// }
     /// assert_eq!(rbuf, b"cdef");
+    /// # }
     /// ```
     pub fn from_mut_slice(fd: RawFd, offs: off_t, buf: &'a mut [u8],
                           prio: libc::c_int, sigev_notify: SigevNotify,
-                          opcode: LioOpcode) -> Pin<Box<AioCb<'a>>> {
+                          opcode: LioOpcode) -> AioCb<'a> {
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        a.0.aio_offset = offs;
-        a.0.aio_nbytes = buf.len() as size_t;
-        a.0.aio_buf = buf.as_ptr() as *mut c_void;
-        a.0.aio_lio_opcode = opcode as libc::c_int;
+        a.aio_offset = offs;
+        a.aio_nbytes = buf.len() as size_t;
+        a.aio_buf = buf.as_ptr() as *mut c_void;
+        a.aio_lio_opcode = opcode as libc::c_int;
 
-        Box::pin(AioCb {
+        AioCb {
             aiocb: a,
             mutable: true,
             in_progress: false,
-            _buffer: PhantomData,
-            _pin: std::marker::PhantomPinned
-        })
+            buffer: Buffer::Phantom(PhantomData),
+        }
+    }
+
+    /// The safest and most flexible way to create an `AioCb`.
+    ///
+    /// Unlike [`from_slice`], this method returns a structure suitable for
+    /// placement on the heap.  It may be used for write operations, but not
+    /// read operations.  Unlike `from_ptr`, this method will ensure that the
+    /// buffer doesn't `drop` while the kernel is still processing it.  Any
+    /// object that can be borrowed as a boxed slice will work.
+    ///
+    /// # Parameters
+    ///
+    /// * `fd`:           File descriptor.  Required for all aio functions.
+    /// * `offs`:         File offset
+    /// * `buf`:          A boxed slice-like object
+    /// * `prio`:         If POSIX Prioritized IO is supported, then the
+    ///                   operation will be prioritized at the process's
+    ///                   priority level minus `prio`
+    /// * `sigev_notify`: Determines how you will be notified of event
+    ///                   completion.
+    /// * `opcode`:       This field is only used for `lio_listio`.  It
+    ///                   determines which operation to use for this individual
+    ///                   aiocb
+    ///
+    /// # Examples
+    ///
+    /// Create an `AioCb` from a Vector and use it for writing
+    ///
+    /// ```
+    /// # use nix::errno::Errno;
+    /// # use nix::Error;
+    /// # use nix::sys::aio::*;
+    /// # use nix::sys::signal::SigevNotify;
+    /// # use std::{thread, time};
+    /// # use std::io::Write;
+    /// # use std::os::unix::io::AsRawFd;
+    /// # use tempfile::tempfile;
+    /// # fn main() {
+    /// let wbuf = Box::new(Vec::from("CDEF"));
+    /// let expected_len = wbuf.len();
+    /// let mut f = tempfile().unwrap();
+    /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
+    ///     2,   //offset
+    ///     wbuf,
+    ///     0,   //priority
+    ///     SigevNotify::SigevNone,
+    ///     LioOpcode::LIO_NOP);
+    /// aiocb.write().unwrap();
+    /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
+    ///     thread::sleep(time::Duration::from_millis(10));
+    /// }
+    /// assert_eq!(aiocb.aio_return().unwrap() as usize, expected_len);
+    /// # }
+    /// ```
+    ///
+    /// Create an `AioCb` from a `Bytes` object
+    ///
+    /// ```
+    /// # use bytes::Bytes;
+    /// # use nix::sys::aio::*;
+    /// # use nix::sys::signal::SigevNotify;
+    /// # use std::os::unix::io::AsRawFd;
+    /// # use tempfile::tempfile;
+    /// # fn main() {
+    /// let wbuf = Box::new(Bytes::from(&b"CDEF"[..]));
+    /// let mut f = tempfile().unwrap();
+    /// let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
+    ///     2,   //offset
+    ///     wbuf,
+    ///     0,   //priority
+    ///     SigevNotify::SigevNone,
+    ///     LioOpcode::LIO_NOP);
+    /// # }
+    /// ```
+    ///
+    /// If a library needs to work with buffers that aren't `Box`ed, it can
+    /// create a `Box`ed container for use with this method.  Here's an example
+    /// using an un`Box`ed `Bytes` object.
+    ///
+    /// ```
+    /// # use bytes::Bytes;
+    /// # use nix::sys::aio::*;
+    /// # use nix::sys::signal::SigevNotify;
+    /// # use std::borrow::Borrow;
+    /// # use std::os::unix::io::AsRawFd;
+    /// # use tempfile::tempfile;
+    /// struct BytesContainer(Bytes);
+    /// impl Borrow<[u8]> for BytesContainer {
+    ///     fn borrow(&self) -> &[u8] {
+    ///         self.0.as_ref()
+    ///     }
+    /// }
+    /// fn main() {
+    ///     let wbuf = Bytes::from(&b"CDEF"[..]);
+    ///     let boxed_wbuf = Box::new(BytesContainer(wbuf));
+    ///     let mut f = tempfile().unwrap();
+    ///     let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
+    ///         2,   //offset
+    ///         boxed_wbuf,
+    ///         0,   //priority
+    ///         SigevNotify::SigevNone,
+    ///         LioOpcode::LIO_NOP);
+    /// }
+    /// ```
+    ///
+    /// [`from_slice`]: #method.from_slice
+    pub fn from_boxed_slice(fd: RawFd, offs: off_t, buf: Box<dyn Borrow<[u8]>>,
+                      prio: libc::c_int, sigev_notify: SigevNotify,
+                      opcode: LioOpcode) -> AioCb<'a> {
+        let mut a = AioCb::common_init(fd, prio, sigev_notify);
+        {
+            let borrowed : &dyn Borrow<[u8]> = buf.borrow();
+            let slice : &[u8] = borrowed.borrow();
+            a.aio_nbytes = slice.len() as size_t;
+            a.aio_buf = slice.as_ptr() as *mut c_void;
+        }
+        a.aio_offset = offs;
+        a.aio_lio_opcode = opcode as libc::c_int;
+
+        AioCb {
+            aiocb: a,
+            mutable: false,
+            in_progress: false,
+            buffer: Buffer::BoxedSlice(buf),
+        }
+    }
+
+    /// The safest and most flexible way to create an `AioCb` for reading.
+    ///
+    /// Like [`from_boxed_slice`], but the slice is a mutable one.  More
+    /// flexible than [`from_mut_slice`], because a wide range of objects can be
+    /// used.
+    ///
+    /// # Examples
+    ///
+    /// Create an `AioCb` from a Vector and use it for reading
+    ///
+    /// ```
+    /// # use nix::errno::Errno;
+    /// # use nix::Error;
+    /// # use nix::sys::aio::*;
+    /// # use nix::sys::signal::SigevNotify;
+    /// # use std::{thread, time};
+    /// # use std::io::Write;
+    /// # use std::os::unix::io::AsRawFd;
+    /// # use tempfile::tempfile;
+    /// # fn main() {
+    /// const INITIAL: &[u8] = b"abcdef123456";
+    /// const LEN: usize = 4;
+    /// let rbuf = Box::new(vec![0; LEN]);
+    /// let mut f = tempfile().unwrap();
+    /// f.write_all(INITIAL).unwrap();
+    /// let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
+    ///     2,   //offset
+    ///     rbuf,
+    ///     0,   //priority
+    ///     SigevNotify::SigevNone,
+    ///     LioOpcode::LIO_NOP);
+    /// aiocb.read().unwrap();
+    /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
+    ///     thread::sleep(time::Duration::from_millis(10));
+    /// }
+    /// assert_eq!(aiocb.aio_return().unwrap() as usize, LEN);
+    /// let mut buffer = aiocb.boxed_mut_slice().unwrap();
+    /// const EXPECT: &[u8] = b"cdef";
+    /// assert_eq!(buffer.borrow_mut(), EXPECT);
+    /// # }
+    /// ```
+    ///
+    /// [`from_boxed_slice`]: #method.from_boxed_slice
+    /// [`from_mut_slice`]: #method.from_mut_slice
+    pub fn from_boxed_mut_slice(fd: RawFd, offs: off_t,
+                                mut buf: Box<dyn BorrowMut<[u8]>>,
+                                prio: libc::c_int, sigev_notify: SigevNotify,
+                                opcode: LioOpcode) -> AioCb<'a> {
+        let mut a = AioCb::common_init(fd, prio, sigev_notify);
+        {
+            let borrowed : &mut dyn BorrowMut<[u8]> = buf.borrow_mut();
+            let slice : &mut [u8] = borrowed.borrow_mut();
+            a.aio_nbytes = slice.len() as size_t;
+            a.aio_buf = slice.as_mut_ptr() as *mut c_void;
+        }
+        a.aio_offset = offs;
+        a.aio_lio_opcode = opcode as libc::c_int;
+
+        AioCb {
+            aiocb: a,
+            mutable: true,
+            in_progress: false,
+            buffer: Buffer::BoxedMutSlice(buf),
+        }
     }
 
     /// Constructs a new `AioCb` from a mutable raw pointer
@@ -270,7 +527,8 @@
     /// Unlike `from_mut_slice`, this method returns a structure suitable for
     /// placement on the heap.  It may be used for both reads and writes.  Due
     /// to its unsafety, this method is not recommended.  It is most useful when
-    /// heap allocation is required.
+    /// heap allocation is required but for some reason the data cannot be
+    /// wrapped in a `struct` that implements `BorrowMut<[u8]>`
     ///
     /// # Parameters
     ///
@@ -294,27 +552,28 @@
     pub unsafe fn from_mut_ptr(fd: RawFd, offs: off_t,
                            buf: *mut c_void, len: usize,
                            prio: libc::c_int, sigev_notify: SigevNotify,
-                           opcode: LioOpcode) -> Pin<Box<AioCb<'a>>> {
+                           opcode: LioOpcode) -> AioCb<'a> {
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        a.0.aio_offset = offs;
-        a.0.aio_nbytes = len;
-        a.0.aio_buf = buf;
-        a.0.aio_lio_opcode = opcode as libc::c_int;
+        a.aio_offset = offs;
+        a.aio_nbytes = len;
+        a.aio_buf = buf;
+        a.aio_lio_opcode = opcode as libc::c_int;
 
-        Box::pin(AioCb {
+        AioCb {
             aiocb: a,
             mutable: true,
             in_progress: false,
-            _buffer: PhantomData,
-            _pin: std::marker::PhantomPinned,
-        })
+            buffer: Buffer::None
+        }
     }
 
     /// Constructs a new `AioCb` from a raw pointer.
     ///
     /// Unlike `from_slice`, this method returns a structure suitable for
     /// placement on the heap.  Due to its unsafety, this method is not
-    /// recommended.  It is most useful when heap allocation is required.
+    /// recommended.  It is most useful when heap allocation is required but for
+    /// some reason the data cannot be wrapped in a `struct` that implements
+    /// `Borrow<[u8]>`
     ///
     /// # Parameters
     ///
@@ -338,49 +597,24 @@
     pub unsafe fn from_ptr(fd: RawFd, offs: off_t,
                            buf: *const c_void, len: usize,
                            prio: libc::c_int, sigev_notify: SigevNotify,
-                           opcode: LioOpcode) -> Pin<Box<AioCb<'a>>> {
+                           opcode: LioOpcode) -> AioCb<'a> {
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        a.0.aio_offset = offs;
-        a.0.aio_nbytes = len;
+        a.aio_offset = offs;
+        a.aio_nbytes = len;
         // casting a const ptr to a mutable ptr here is ok, because we set the
         // AioCb's mutable field to false
-        a.0.aio_buf = buf as *mut c_void;
-        a.0.aio_lio_opcode = opcode as libc::c_int;
-
-        Box::pin(AioCb {
-            aiocb: a,
-            mutable: false,
-            in_progress: false,
-            _buffer: PhantomData,
-            _pin: std::marker::PhantomPinned
-        })
-    }
-
-    // Private helper
-    fn from_slice_unpinned(fd: RawFd, offs: off_t, buf: &'a [u8],
-                           prio: libc::c_int, sigev_notify: SigevNotify,
-                           opcode: LioOpcode) -> AioCb
-    {
-        let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        a.0.aio_offset = offs;
-        a.0.aio_nbytes = buf.len() as size_t;
-        // casting an immutable buffer to a mutable pointer looks unsafe,
-        // but technically its only unsafe to dereference it, not to create
-        // it.
-        a.0.aio_buf = buf.as_ptr() as *mut c_void;
-        assert!(opcode != LioOpcode::LIO_READ, "Can't read into an immutable buffer");
-        a.0.aio_lio_opcode = opcode as libc::c_int;
+        a.aio_buf = buf as *mut c_void;
+        a.aio_lio_opcode = opcode as libc::c_int;
 
         AioCb {
             aiocb: a,
             mutable: false,
             in_progress: false,
-            _buffer: PhantomData,
-            _pin: std::marker::PhantomPinned
+            buffer: Buffer::None
         }
     }
 
-    /// Like [`AioCb::from_mut_slice`], but works on constant slices rather than
+    /// Like `from_mut_slice`, but works on constant slices rather than
     /// mutable slices.
     ///
     /// An `AioCb` created this way cannot be used with `read`, and its
@@ -400,6 +634,7 @@
     /// # use std::{thread, time};
     /// # use std::os::unix::io::AsRawFd;
     /// # use tempfile::tempfile;
+    /// # fn main() {
     /// const WBUF: &[u8] = b"abcdef123456";
     /// let mut f = tempfile().unwrap();
     /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
@@ -409,10 +644,11 @@
     ///     SigevNotify::SigevNone,
     ///     LioOpcode::LIO_NOP);
     /// aiocb.write().unwrap();
-    /// while (aiocb.error() == Err(Errno::EINPROGRESS)) {
+    /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
     ///     thread::sleep(time::Duration::from_millis(10));
     /// }
     /// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
+    /// # }
     /// ```
     // Note: another solution to the problem of writing const buffers would be
     // to genericize AioCb for both &mut [u8] and &[u8] buffers.  AioCb::read
@@ -421,14 +657,27 @@
     // AioCb, and they must all be of the same type.
     pub fn from_slice(fd: RawFd, offs: off_t, buf: &'a [u8],
                       prio: libc::c_int, sigev_notify: SigevNotify,
-                      opcode: LioOpcode) -> Pin<Box<AioCb>>
-    {
-        Box::pin(AioCb::from_slice_unpinned(fd, offs, buf, prio, sigev_notify,
-                                            opcode))
+                      opcode: LioOpcode) -> AioCb {
+        let mut a = AioCb::common_init(fd, prio, sigev_notify);
+        a.aio_offset = offs;
+        a.aio_nbytes = buf.len() as size_t;
+        // casting an immutable buffer to a mutable pointer looks unsafe,
+        // but technically its only unsafe to dereference it, not to create
+        // it.
+        a.aio_buf = buf.as_ptr() as *mut c_void;
+        assert!(opcode != LioOpcode::LIO_READ, "Can't read into an immutable buffer");
+        a.aio_lio_opcode = opcode as libc::c_int;
+
+        AioCb {
+            aiocb: a,
+            mutable: false,
+            in_progress: false,
+            buffer: Buffer::None,
+        }
     }
 
     fn common_init(fd: RawFd, prio: libc::c_int,
-                   sigev_notify: SigevNotify) -> LibcAiocb {
+                   sigev_notify: SigevNotify) -> libc::aiocb {
         // Use mem::zeroed instead of explicitly zeroing each field, because the
         // number and name of reserved fields is OS-dependent.  On some OSes,
         // some reserved fields are used the kernel for state, and must be
@@ -437,18 +686,12 @@
         a.aio_fildes = fd;
         a.aio_reqprio = prio;
         a.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
-        LibcAiocb(a)
+        a
     }
 
     /// Update the notification settings for an existing `aiocb`
-    pub fn set_sigev_notify(self: &mut Pin<Box<Self>>,
-                            sigev_notify: SigevNotify)
-    {
-        // Safe because we don't move any of the data
-        let selfp = unsafe {
-            self.as_mut().get_unchecked_mut()
-        };
-        selfp.aiocb.0.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
+    pub fn set_sigev_notify(&mut self, sigev_notify: SigevNotify) {
+        self.aiocb.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
     }
 
     /// Cancels an outstanding AIO request.
@@ -474,6 +717,7 @@
     /// # use std::io::Write;
     /// # use std::os::unix::io::AsRawFd;
     /// # use tempfile::tempfile;
+    /// # fn main() {
     /// let wbuf = b"CDEF";
     /// let mut f = tempfile().unwrap();
     /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
@@ -485,43 +729,28 @@
     /// aiocb.write().unwrap();
     /// let cs = aiocb.cancel().unwrap();
     /// if cs == AioCancelStat::AioNotCanceled {
-    ///     while (aiocb.error() == Err(Errno::EINPROGRESS)) {
+    ///     while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
     ///         thread::sleep(time::Duration::from_millis(10));
     ///     }
     /// }
     /// // Must call `aio_return`, but ignore the result
     /// let _ = aiocb.aio_return();
+    /// # }
     /// ```
     ///
     /// # References
     ///
-    /// [aio_cancel](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
-    pub fn cancel(self: &mut Pin<Box<Self>>) -> Result<AioCancelStat> {
-        let r = unsafe {
-            let selfp = self.as_mut().get_unchecked_mut();
-            libc::aio_cancel(selfp.aiocb.0.aio_fildes, &mut selfp.aiocb.0)
-        };
-        match r {
+    /// [aio_cancel](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
+    pub fn cancel(&mut self) -> Result<AioCancelStat> {
+        match unsafe { libc::aio_cancel(self.aiocb.aio_fildes, &mut self.aiocb) } {
             libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
             libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
             libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
-            -1 => Err(Errno::last()),
+            -1 => Err(Error::last()),
             _ => panic!("unknown aio_cancel return value")
         }
     }
 
-    fn error_unpinned(&mut self) -> Result<()> {
-        let r = unsafe {
-            libc::aio_error(&mut self.aiocb.0 as *mut libc::aiocb)
-        };
-        match r {
-            0 => Ok(()),
-            num if num > 0 => Err(Errno::from_i32(num)),
-            -1 => Err(Errno::last()),
-            num => panic!("unknown aio_error return value {:?}", num)
-        }
-    }
-
     /// Retrieve error status of an asynchronous operation.
     ///
     /// If the request has not yet completed, returns `EINPROGRESS`.  Otherwise,
@@ -540,6 +769,7 @@
     /// # use std::{thread, time};
     /// # use std::os::unix::io::AsRawFd;
     /// # use tempfile::tempfile;
+    /// # fn main() {
     /// const WBUF: &[u8] = b"abcdef123456";
     /// let mut f = tempfile().unwrap();
     /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
@@ -549,39 +779,37 @@
     ///     SigevNotify::SigevNone,
     ///     LioOpcode::LIO_NOP);
     /// aiocb.write().unwrap();
-    /// while (aiocb.error() == Err(Errno::EINPROGRESS)) {
+    /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
     ///     thread::sleep(time::Duration::from_millis(10));
     /// }
     /// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
+    /// # }
     /// ```
     ///
     /// # References
     ///
-    /// [aio_error](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_error.html)
-    pub fn error(self: &mut Pin<Box<Self>>) -> Result<()> {
-        // Safe because error_unpinned doesn't move the data
-        let selfp = unsafe {
-            self.as_mut().get_unchecked_mut()
-        };
-        selfp.error_unpinned()
+    /// [aio_error](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_error.html)
+    pub fn error(&mut self) -> Result<()> {
+        match unsafe { libc::aio_error(&mut self.aiocb as *mut libc::aiocb) } {
+            0 => Ok(()),
+            num if num > 0 => Err(Error::from_errno(Errno::from_i32(num))),
+            -1 => Err(Error::last()),
+            num => panic!("unknown aio_error return value {:?}", num)
+        }
     }
 
     /// An asynchronous version of `fsync(2)`.
     ///
     /// # References
     ///
-    /// [aio_fsync](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_fsync.html)
-    pub fn fsync(self: &mut Pin<Box<Self>>, mode: AioFsyncMode) -> Result<()> {
-        // Safe because we don't move the libc::aiocb
-        unsafe {
-            let selfp = self.as_mut().get_unchecked_mut();
-            Errno::result({
-                let p: *mut libc::aiocb = &mut selfp.aiocb.0;
+    /// [aio_fsync](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_fsync.html)
+    pub fn fsync(&mut self, mode: AioFsyncMode) -> Result<()> {
+        let p: *mut libc::aiocb = &mut self.aiocb;
+        Errno::result(unsafe {
                 libc::aio_fsync(mode as libc::c_int, p)
-            }).map(|_| {
-                selfp.in_progress = true;
-            })
-        }
+        }).map(|_| {
+            self.in_progress = true;
+        })
     }
 
     /// Returns the `aiocb`'s `LioOpcode` field
@@ -589,7 +817,7 @@
     /// If the value cannot be represented as an `LioOpcode`, returns `None`
     /// instead.
     pub fn lio_opcode(&self) -> Option<LioOpcode> {
-        match self.aiocb.0.aio_lio_opcode {
+        match self.aiocb.aio_lio_opcode {
             libc::LIO_READ => Some(LioOpcode::LIO_READ),
             libc::LIO_WRITE => Some(LioOpcode::LIO_WRITE),
             libc::LIO_NOP => Some(LioOpcode::LIO_NOP),
@@ -603,49 +831,37 @@
     /// number of bytes actually read or written by a completed operation, use
     /// `aio_return` instead.
     pub fn nbytes(&self) -> usize {
-        self.aiocb.0.aio_nbytes
+        self.aiocb.aio_nbytes
     }
 
     /// Returns the file offset stored in the `AioCb`
     pub fn offset(&self) -> off_t {
-        self.aiocb.0.aio_offset
+        self.aiocb.aio_offset
     }
 
     /// Returns the priority of the `AioCb`
     pub fn priority(&self) -> libc::c_int {
-        self.aiocb.0.aio_reqprio
+        self.aiocb.aio_reqprio
     }
 
     /// Asynchronously reads from a file descriptor into a buffer
     ///
     /// # References
     ///
-    /// [aio_read](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_read.html)
-    pub fn read(self: &mut Pin<Box<Self>>) -> Result<()> {
+    /// [aio_read](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_read.html)
+    pub fn read(&mut self) -> Result<()> {
         assert!(self.mutable, "Can't read into an immutable buffer");
-        // Safe because we don't move anything
-        let selfp = unsafe {
-            self.as_mut().get_unchecked_mut()
-        };
-        Errno::result({
-            let p: *mut libc::aiocb = &mut selfp.aiocb.0;
-            unsafe { libc::aio_read(p) }
+        let p: *mut libc::aiocb = &mut self.aiocb;
+        Errno::result(unsafe {
+            libc::aio_read(p)
         }).map(|_| {
-            selfp.in_progress = true;
+            self.in_progress = true;
         })
     }
 
     /// Returns the `SigEvent` stored in the `AioCb`
     pub fn sigevent(&self) -> SigEvent {
-        SigEvent::from(&self.aiocb.0.aio_sigevent)
-    }
-
-    fn aio_return_unpinned(&mut self) -> Result<isize> {
-        unsafe {
-            let p: *mut libc::aiocb = &mut self.aiocb.0;
-            self.in_progress = false;
-            Errno::result(libc::aio_return(p))
-        }
+        SigEvent::from(&self.aiocb.aio_sigevent)
     }
 
     /// Retrieve return status of an asynchronous operation.
@@ -656,33 +872,28 @@
     ///
     /// # References
     ///
-    /// [aio_return](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html)
+    /// [aio_return](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html)
     // Note: this should be just `return`, but that's a reserved word
-    pub fn aio_return(self: &mut Pin<Box<Self>>) -> Result<isize> {
-        // Safe because aio_return_unpinned does not move the data
-        let selfp = unsafe {
-            self.as_mut().get_unchecked_mut()
-        };
-        selfp.aio_return_unpinned()
+    pub fn aio_return(&mut self) -> Result<isize> {
+        let p: *mut libc::aiocb = &mut self.aiocb;
+        self.in_progress = false;
+        Errno::result(unsafe { libc::aio_return(p) })
     }
 
     /// Asynchronously writes from a buffer to a file descriptor
     ///
     /// # References
     ///
-    /// [aio_write](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_write.html)
-    pub fn write(self: &mut Pin<Box<Self>>) -> Result<()> {
-        // Safe because we don't move anything
-        let selfp = unsafe {
-            self.as_mut().get_unchecked_mut()
-        };
-        Errno::result({
-            let p: *mut libc::aiocb = &mut selfp.aiocb.0;
-            unsafe{ libc::aio_write(p) }
+    /// [aio_write](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_write.html)
+    pub fn write(&mut self) -> Result<()> {
+        let p: *mut libc::aiocb = &mut self.aiocb;
+        Errno::result(unsafe {
+            libc::aio_write(p)
         }).map(|_| {
-            selfp.in_progress = true;
+            self.in_progress = true;
         })
     }
+
 }
 
 /// Cancels outstanding AIO requests for a given file descriptor.
@@ -701,6 +912,7 @@
 /// # use std::io::Write;
 /// # use std::os::unix::io::AsRawFd;
 /// # use tempfile::tempfile;
+/// # fn main() {
 /// let wbuf = b"CDEF";
 /// let mut f = tempfile().unwrap();
 /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
@@ -712,23 +924,24 @@
 /// aiocb.write().unwrap();
 /// let cs = aio_cancel_all(f.as_raw_fd()).unwrap();
 /// if cs == AioCancelStat::AioNotCanceled {
-///     while (aiocb.error() == Err(Errno::EINPROGRESS)) {
+///     while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
 ///         thread::sleep(time::Duration::from_millis(10));
 ///     }
 /// }
 /// // Must call `aio_return`, but ignore the result
 /// let _ = aiocb.aio_return();
+/// # }
 /// ```
 ///
 /// # References
 ///
-/// [`aio_cancel`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
+/// [`aio_cancel`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
 pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> {
     match unsafe { libc::aio_cancel(fd, null_mut()) } {
         libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
         libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
         libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
-        -1 => Err(Errno::last()),
+        -1 => Err(Error::last()),
         _ => panic!("unknown aio_cancel return value")
     }
 }
@@ -747,6 +960,7 @@
 /// # use nix::sys::signal::SigevNotify;
 /// # use std::os::unix::io::AsRawFd;
 /// # use tempfile::tempfile;
+/// # fn main() {
 /// const WBUF: &[u8] = b"abcdef123456";
 /// let mut f = tempfile().unwrap();
 /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
@@ -756,14 +970,15 @@
 ///     SigevNotify::SigevNone,
 ///     LioOpcode::LIO_NOP);
 /// aiocb.write().unwrap();
-/// aio_suspend(&[aiocb.as_ref()], None).expect("aio_suspend failed");
+/// aio_suspend(&[&aiocb], None).expect("aio_suspend failed");
 /// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
+/// # }
 /// ```
 /// # References
 ///
-/// [`aio_suspend`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_suspend.html)
-pub fn aio_suspend(list: &[Pin<&AioCb>], timeout: Option<TimeSpec>) -> Result<()> {
-    let plist = list as *const [Pin<&AioCb>] as *const [*const libc::aiocb];
+/// [`aio_suspend`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_suspend.html)
+pub fn aio_suspend(list: &[&AioCb], timeout: Option<TimeSpec>) -> Result<()> {
+    let plist = list as *const [&AioCb] as *const [*const libc::aiocb];
     let p = plist as *const *const libc::aiocb;
     let timep = match timeout {
         None    => null::<libc::timespec>(),
@@ -777,7 +992,7 @@
 impl<'a> Debug for AioCb<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         fmt.debug_struct("AioCb")
-            .field("aiocb", &self.aiocb.0)
+            .field("aiocb", &self.aiocb)
             .field("mutable", &self.mutable)
             .field("in_progress", &self.in_progress)
             .finish()
@@ -803,9 +1018,7 @@
     ///
     /// [`AioCb`]: struct.AioCb.html
     /// [`listio`]: #method.listio
-    // Their locations in memory must be fixed once they are passed to the
-    // kernel.  So this field must be non-public so the user can't swap.
-    aiocbs: Box<[AioCb<'a>]>,
+    pub aiocbs: Vec<AioCb<'a>>,
 
     /// The actual list passed to `libc::lio_listio`.
     ///
@@ -819,24 +1032,15 @@
     results: Vec<Option<Result<isize>>>
 }
 
-/// LioCb can't automatically impl Send and Sync just because of the raw
-/// pointers in list.  But that's stupid.  There's no reason that raw pointers
-/// should automatically be non-Send
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-unsafe impl<'a> Send for LioCb<'a> {}
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-unsafe impl<'a> Sync for LioCb<'a> {}
-
 #[cfg(not(any(target_os = "ios", target_os = "macos")))]
 impl<'a> LioCb<'a> {
-    /// Are no [`AioCb`]s contained?
-    pub fn is_empty(&self) -> bool {
-        self.aiocbs.is_empty()
-    }
-
-    /// Return the number of individual [`AioCb`]s contained.
-    pub fn len(&self) -> usize {
-        self.aiocbs.len()
+    /// Initialize an empty `LioCb`
+    pub fn with_capacity(capacity: usize) -> LioCb<'a> {
+        LioCb {
+            aiocbs: Vec::with_capacity(capacity),
+            list: Vec::with_capacity(capacity),
+            results: Vec::with_capacity(capacity)
+        }
     }
 
     /// Submits multiple asynchronous I/O requests with a single system call.
@@ -862,25 +1066,25 @@
     /// # use nix::sys::signal::SigevNotify;
     /// # use std::os::unix::io::AsRawFd;
     /// # use tempfile::tempfile;
+    /// # fn main() {
     /// const WBUF: &[u8] = b"abcdef123456";
     /// let mut f = tempfile().unwrap();
-    /// let mut liocb = LioCbBuilder::with_capacity(1)
-    ///     .emplace_slice(
-    ///         f.as_raw_fd(),
-    ///         2,   //offset
-    ///         WBUF,
-    ///         0,   //priority
-    ///         SigevNotify::SigevNone,
-    ///         LioOpcode::LIO_WRITE
-    ///     ).finish();
+    /// let mut liocb = LioCb::with_capacity(1);
+    /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
+    ///     2,   //offset
+    ///     WBUF,
+    ///     0,   //priority
+    ///     SigevNotify::SigevNone,
+    ///     LioOpcode::LIO_WRITE));
     /// liocb.listio(LioMode::LIO_WAIT,
     ///              SigevNotify::SigevNone).unwrap();
     /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
+    /// # }
     /// ```
     ///
     /// # References
     ///
-    /// [`lio_listio`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
+    /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
     ///
     /// [`aio_suspend`]: fn.aio_suspend.html
     /// [`AioCb::error`]: struct.AioCb.html#method.error
@@ -889,7 +1093,7 @@
         let sigev = SigEvent::new(sigev_notify);
         let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
         self.list.clear();
-        for a in &mut self.aiocbs.iter_mut() {
+        for a in &mut self.aiocbs {
             a.in_progress = true;
             self.list.push(a as *mut AioCb<'a>
                              as *mut libc::aiocb);
@@ -920,31 +1124,31 @@
     /// # use std::os::unix::io::AsRawFd;
     /// # use std::{thread, time};
     /// # use tempfile::tempfile;
+    /// # fn main() {
     /// const WBUF: &[u8] = b"abcdef123456";
     /// let mut f = tempfile().unwrap();
-    /// let mut liocb = LioCbBuilder::with_capacity(1)
-    ///     .emplace_slice(
-    ///         f.as_raw_fd(),
-    ///         2,   //offset
-    ///         WBUF,
-    ///         0,   //priority
-    ///         SigevNotify::SigevNone,
-    ///         LioOpcode::LIO_WRITE
-    ///     ).finish();
+    /// let mut liocb = LioCb::with_capacity(1);
+    /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
+    ///     2,   //offset
+    ///     WBUF,
+    ///     0,   //priority
+    ///     SigevNotify::SigevNone,
+    ///     LioOpcode::LIO_WRITE));
     /// let mut err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
-    /// while err == Err(Errno::EIO) ||
-    ///       err == Err(Errno::EAGAIN) {
+    /// while err == Err(Error::Sys(Errno::EIO)) ||
+    ///       err == Err(Error::Sys(Errno::EAGAIN)) {
     ///     thread::sleep(time::Duration::from_millis(10));
     ///     err = liocb.listio_resubmit(LioMode::LIO_WAIT, SigevNotify::SigevNone);
     /// }
     /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
+    /// # }
     /// ```
     ///
     /// # References
     ///
-    /// [`lio_listio`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
+    /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
     ///
-    /// [`lio_listio`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html
+    /// [`lio_listio`]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html
     /// [`LioCb::aio_return`]: struct.LioCb.html#method.aio_return
     // Note: the addresses of any EINPROGRESS or EOK aiocbs _must_ not be
     // changed by this method, because the kernel relies on their addresses
@@ -966,18 +1170,18 @@
                 // Already collected final status for this operation
                 continue;
             }
-            match a.error_unpinned() {
+            match a.error() {
                 Ok(()) => {
                     // aiocb is complete; collect its status and don't resubmit
-                    self.results[i] = Some(a.aio_return_unpinned());
+                    self.results[i] = Some(a.aio_return());
                 },
-                Err(Errno::EAGAIN) => {
+                Err(Error::Sys(Errno::EAGAIN)) => {
                     self.list.push(a as *mut AioCb<'a> as *mut libc::aiocb);
                 },
-                Err(Errno::EINPROGRESS) => {
+                Err(Error::Sys(Errno::EINPROGRESS)) => {
                     // aiocb is was successfully queued; no need to do anything
                 },
-                Err(Errno::EINVAL) => panic!(
+                Err(Error::Sys(Errno::EINVAL)) => panic!(
                     "AioCb was never submitted, or already finalized"),
                 _ => unreachable!()
             }
@@ -998,7 +1202,7 @@
     /// [`LioCb::listio_resubmit`]: #method.listio_resubmit
     pub fn aio_return(&mut self, i: usize) -> Result<isize> {
         if i >= self.results.len() || self.results[i].is_none() {
-            self.aiocbs[i].aio_return_unpinned()
+            self.aiocbs[i].aio_return()
         } else {
             self.results[i].unwrap()
         }
@@ -1014,7 +1218,7 @@
     /// [`LioCb::listio_resubmit`]: #method.listio_resubmit
     pub fn error(&mut self, i: usize) -> Result<()> {
         if i >= self.results.len() || self.results[i].is_none() {
-            self.aiocbs[i].error_unpinned()
+            self.aiocbs[i].error()
         } else {
             Ok(())
         }
@@ -1030,93 +1234,13 @@
     }
 }
 
-/// Used to construct `LioCb`
-// This must be a separate class from LioCb due to pinning constraints.  LioCb
-// must use a boxed slice of AioCbs so they will have stable storage, but
-// LioCbBuilder must use a Vec to make construction possible when the final size
-// is unknown.
 #[cfg(not(any(target_os = "ios", target_os = "macos")))]
-#[derive(Debug)]
-pub struct LioCbBuilder<'a> {
-    /// A collection of [`AioCb`]s.
-    ///
-    /// [`AioCb`]: struct.AioCb.html
-    pub aiocbs: Vec<AioCb<'a>>,
-}
-
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-impl<'a> LioCbBuilder<'a> {
-    /// Initialize an empty `LioCb`
-    pub fn with_capacity(capacity: usize) -> LioCbBuilder<'a> {
-        LioCbBuilder {
-            aiocbs: Vec::with_capacity(capacity),
-        }
-    }
-
-    /// Add a new operation on an immutable slice to the [`LioCb`] under
-    /// construction.
-    ///
-    /// Arguments are the same as for [`AioCb::from_slice`]
-    ///
-    /// [`LioCb`]: struct.LioCb.html
-    /// [`AioCb::from_slice`]: struct.AioCb.html#method.from_slice
-    pub fn emplace_slice(mut self, fd: RawFd, offs: off_t, buf: &'a [u8],
-                         prio: libc::c_int, sigev_notify: SigevNotify,
-                         opcode: LioOpcode) -> Self
-    {
-        self.aiocbs.push(AioCb::from_slice_unpinned(fd, offs, buf, prio,
-                                                    sigev_notify, opcode));
-        self
-    }
-
-    /// Add a new operation on a mutable slice to the [`LioCb`] under
-    /// construction.
-    ///
-    /// Arguments are the same as for [`AioCb::from_mut_slice`]
-    ///
-    /// [`LioCb`]: struct.LioCb.html
-    /// [`AioCb::from_mut_slice`]: struct.AioCb.html#method.from_mut_slice
-    pub fn emplace_mut_slice(mut self, fd: RawFd, offs: off_t,
-                             buf: &'a mut [u8], prio: libc::c_int,
-                             sigev_notify: SigevNotify, opcode: LioOpcode)
-        -> Self
-    {
-        self.aiocbs.push(AioCb::from_mut_slice_unpinned(fd, offs, buf, prio,
-                                                        sigev_notify, opcode));
-        self
-    }
-
-    /// Finalize this [`LioCb`].
-    ///
-    /// Afterwards it will be possible to issue the operations with
-    /// [`LioCb::listio`].  Conversely, it will no longer be possible to add new
-    /// operations with [`LioCbBuilder::emplace_slice`] or
-    /// [`LioCbBuilder::emplace_mut_slice`].
-    ///
-    /// [`LioCb::listio`]: struct.LioCb.html#method.listio
-    /// [`LioCb::from_mut_slice`]: struct.LioCb.html#method.from_mut_slice
-    /// [`LioCb::from_slice`]: struct.LioCb.html#method.from_slice
-    pub fn finish(self) -> LioCb<'a> {
-        let len = self.aiocbs.len();
+impl<'a> From<Vec<AioCb<'a>>> for LioCb<'a> {
+    fn from(src: Vec<AioCb<'a>>) -> LioCb<'a> {
         LioCb {
-            aiocbs: self.aiocbs.into(),
-            list: Vec::with_capacity(len),
-            results: Vec::with_capacity(len)
+            list: Vec::with_capacity(src.capacity()),
+            results: Vec::with_capacity(src.capacity()),
+            aiocbs: src,
         }
     }
 }
-
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-#[cfg(test)]
-mod t {
-    use super::*;
-
-    // It's important that `LioCb` be `UnPin`.  The tokio-file crate relies on
-    // it.
-    #[test]
-    fn liocb_is_unpin() {
-        use assert_impl::assert_impl;
-
-        assert_impl!(Unpin: LioCb);
-    }
-}
diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs
index 6bc2a25..2437bbe 100644
--- a/src/sys/epoll.rs
+++ b/src/sys/epoll.rs
@@ -4,6 +4,7 @@
 use std::os::unix::io::RawFd;
 use std::ptr;
 use std::mem;
+use crate::Error;
 
 libc_bitflags!(
     pub struct EpollFlags: c_int {
@@ -29,7 +30,6 @@
 
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 #[repr(i32)]
-#[non_exhaustive]
 pub enum EpollOp {
     EpollCtlAdd = libc::EPOLL_CTL_ADD,
     EpollCtlDel = libc::EPOLL_CTL_DEL,
@@ -86,7 +86,7 @@
 {
     let mut event: Option<&mut EpollEvent> = event.into();
     if event.is_none() && op != EpollOp::EpollCtlDel {
-        Err(Errno::EINVAL)
+        Err(Error::Sys(Errno::EINVAL))
     } else {
         let res = unsafe {
             if let Some(ref mut event) = event {
diff --git a/src/sys/event.rs b/src/sys/event.rs
index c648f5e..8050af3 100644
--- a/src/sys/event.rs
+++ b/src/sys/event.rs
@@ -6,9 +6,9 @@
 use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
 #[cfg(target_os = "netbsd")]
 use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
-use std::convert::TryInto;
 use std::os::unix::io::RawFd;
 use std::ptr;
+use std::mem;
 
 // Redefine kevent in terms of programmer-friendly enums and bitfields.
 #[repr(C)]
@@ -36,7 +36,6 @@
 libc_enum! {
     #[cfg_attr(target_os = "netbsd", repr(u32))]
     #[cfg_attr(not(target_os = "netbsd"), repr(i16))]
-    #[non_exhaustive]
     pub enum EventFilter {
         EVFILT_AIO,
         /// Returns whenever there is no remaining data in the write buffer
@@ -76,7 +75,6 @@
         EVFILT_VNODE,
         EVFILT_WRITE,
     }
-    impl TryFrom<type_of_event_filter>
 }
 
 #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
@@ -234,8 +232,8 @@
         self.kevent.ident
     }
 
-    pub fn filter(&self) -> Result<EventFilter> {
-        self.kevent.filter.try_into()
+    pub fn filter(&self) -> EventFilter {
+        unsafe { mem::transmute(self.kevent.filter as type_of_event_filter) }
     }
 
     pub fn flags(&self) -> EventFlag {
@@ -314,8 +312,6 @@
 
 #[test]
 fn test_struct_kevent() {
-    use std::mem;
-
     let udata : intptr_t = 12345;
 
     let actual = KEvent::new(0xdead_beef,
@@ -325,24 +321,10 @@
                              0x1337,
                              udata);
     assert_eq!(0xdead_beef, actual.ident());
-    let filter = actual.kevent.filter;
-    assert_eq!(libc::EVFILT_READ, filter);
+    assert_eq!(libc::EVFILT_READ, actual.filter() as type_of_event_filter);
     assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
     assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
     assert_eq!(0x1337, actual.data() as type_of_data);
     assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata);
     assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
 }
-
-#[test]
-fn test_kevent_filter() {
-    let udata : intptr_t = 12345;
-
-    let actual = KEvent::new(0xdead_beef,
-                             EventFilter::EVFILT_READ,
-                             EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
-                             FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
-                             0x1337,
-                             udata);
-    assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
-}
diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs
index c54f952..baaaa89 100644
--- a/src/sys/eventfd.rs
+++ b/src/sys/eventfd.rs
@@ -1,3 +1,4 @@
+use libc;
 use std::os::unix::io::RawFd;
 use crate::Result;
 use crate::errno::Errno;
diff --git a/src/sys/inotify.rs b/src/sys/inotify.rs
index 3f5ae22..4880a4a 100644
--- a/src/sys/inotify.rs
+++ b/src/sys/inotify.rs
@@ -2,8 +2,8 @@
 //!
 //! Inotify is a Linux-only API to monitor filesystems events.
 //!
-//! For more documentation, please read [inotify(7)](https://man7.org/linux/man-pages/man7/inotify.7.html).
-//!
+//! For more documentation, please read [inotify(7)](http://man7.org/linux/man-pages/man7/inotify.7.html).
+//! 
 //! # Examples
 //!
 //! Monitor all events happening in directory "test":
@@ -86,7 +86,7 @@
 
 /// This object is returned when you create a new watch on an inotify instance.
 /// It is then returned as part of an event once triggered. It allows you to
-/// know which watch triggered which event.
+/// know which watch triggered which event. 
 #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
 pub struct WatchDescriptor {
     wd: i32
@@ -94,18 +94,18 @@
 
 /// A single inotify event.
 ///
-/// For more documentation see, [inotify(7)](https://man7.org/linux/man-pages/man7/inotify.7.html).
+/// For more documentation see, [inotify(7)](http://man7.org/linux/man-pages/man7/inotify.7.html).
 #[derive(Debug)]
 pub struct InotifyEvent {
     /// Watch descriptor. This field corresponds to the watch descriptor you
     /// were issued when calling add_watch. It allows you to know which watch
-    /// this event comes from.
+    /// this event comes from. 
     pub wd: WatchDescriptor,
     /// Event mask. This field is a bitfield describing the exact event that
     /// occured.
     pub mask: AddWatchFlags,
     /// This cookie is a number that allows you to connect related events. For
-    /// now only IN_MOVED_FROM and IN_MOVED_TO can be connected.
+    /// now only IN_MOVED_FROM and IN_MOVED_TO can be connected. 
     pub cookie: u32,
     /// Filename. This field exists only if the event was triggered for a file
     /// inside the watched directory.
@@ -117,7 +117,7 @@
     ///
     /// Returns a Result containing an inotify instance.
     ///
-    /// For more information see, [inotify_init(2)](https://man7.org/linux/man-pages/man2/inotify_init.2.html).
+    /// For more information see, [inotify_init(2)](http://man7.org/linux/man-pages/man2/inotify_init.2.html).
     pub fn init(flags: InitFlags) -> Result<Inotify> {
         let res = Errno::result(unsafe {
             libc::inotify_init1(flags.bits())
@@ -126,14 +126,14 @@
         res.map(|fd| Inotify { fd })
     }
 
-    /// Adds a new watch on the target file or directory.
+    /// Adds a new watch on the target file or directory. 
     ///
-    /// Returns a watch descriptor. This is not a File Descriptor!
+    /// Returns a watch descriptor. This is not a File Descriptor! 
     ///
-    /// For more information see, [inotify_add_watch(2)](https://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
+    /// For more information see, [inotify_add_watch(2)](http://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
     pub fn add_watch<P: ?Sized + NixPath>(self,
                                           path: &P,
-                                          mask: AddWatchFlags)
+                                          mask: AddWatchFlags) 
                                             -> Result<WatchDescriptor>
     {
         let res = path.with_nix_path(|cstr| {
@@ -150,7 +150,7 @@
     ///
     /// Returns an EINVAL error if the watch descriptor is invalid.
     ///
-    /// For more information see, [inotify_rm_watch(2)](https://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
+    /// For more information see, [inotify_rm_watch(2)](http://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
     #[cfg(target_os = "linux")]
     pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
         let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd) };
@@ -167,8 +167,8 @@
 
     /// Reads a collection of events from the inotify file descriptor. This call
     /// can either be blocking or non blocking depending on whether IN_NONBLOCK
-    /// was set at initialization.
-    ///
+    /// was set at initialization. 
+    /// 
     /// Returns as many events as available. If the call was non blocking and no
     /// events could be read then the EAGAIN error is returned.
     pub fn read_events(self) -> Result<Vec<InotifyEvent>> {
@@ -194,14 +194,14 @@
             let name = match event.len {
                 0 => None,
                 _ => {
-                    let ptr = unsafe {
+                    let ptr = unsafe { 
                         buffer
                             .as_ptr()
                             .add(offset + header_size)
                             as *const c_char
                     };
                     let cstr = unsafe { CStr::from_ptr(ptr) };
-
+                
                     Some(OsStr::from_bytes(cstr.to_bytes()).to_owned())
                 }
             };
diff --git a/src/sys/ioctl/bsd.rs b/src/sys/ioctl/bsd.rs
index 4ce4d33..f39c0eb 100644
--- a/src/sys/ioctl/bsd.rs
+++ b/src/sys/ioctl/bsd.rs
@@ -1,12 +1,6 @@
 /// The datatype used for the ioctl number
 #[doc(hidden)]
-#[cfg(not(target_os = "illumos"))]
 pub type ioctl_num_type = ::libc::c_ulong;
-
-#[doc(hidden)]
-#[cfg(target_os = "illumos")]
-pub type ioctl_num_type = ::libc::c_int;
-
 /// The datatype used for the 3rd argument
 #[doc(hidden)]
 pub type ioctl_param_type = ::libc::c_int;
@@ -18,7 +12,6 @@
     #[doc(hidden)]
     pub const OUT: ioctl_num_type = 0x4000_0000;
     #[doc(hidden)]
-    #[allow(overflowing_literals)]
     pub const IN: ioctl_num_type = 0x8000_0000;
     #[doc(hidden)]
     pub const INOUT: ioctl_num_type = IN|OUT;
diff --git a/src/sys/ioctl/mod.rs b/src/sys/ioctl/mod.rs
index 203b7d0..8858a9d 100644
--- a/src/sys/ioctl/mod.rs
+++ b/src/sys/ioctl/mod.rs
@@ -104,7 +104,7 @@
 //! respectively. To determine the specific `write_` variant to use you'll need to find
 //! what the argument type is supposed to be. If it's an `int`, then `write_int` should be used,
 //! otherwise it should be a pointer and `write_ptr` should be used. On Linux the
-//! [`ioctl_list` man page](https://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a
+//! [`ioctl_list` man page](http://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a
 //! large number of `ioctl`s and describes their argument data type.
 //!
 //! Using "bad" `ioctl`s
@@ -232,7 +232,6 @@
 
 #[cfg(any(target_os = "dragonfly",
           target_os = "freebsd",
-          target_os = "illumos",
           target_os = "ios",
           target_os = "macos",
           target_os = "netbsd",
@@ -242,7 +241,6 @@
 
 #[cfg(any(target_os = "dragonfly",
           target_os = "freebsd",
-          target_os = "illumos",
           target_os = "ios",
           target_os = "macos",
           target_os = "netbsd",
diff --git a/src/sys/memfd.rs b/src/sys/memfd.rs
index 642676b..51b7e6b 100644
--- a/src/sys/memfd.rs
+++ b/src/sys/memfd.rs
@@ -1,43 +1,16 @@
-//! Interfaces for managing memory-backed files.
-
+use libc;
 use std::os::unix::io::RawFd;
 use crate::Result;
 use crate::errno::Errno;
 use std::ffi::CStr;
 
 libc_bitflags!(
-    /// Options that change the behavior of [`memfd_create`].
     pub struct MemFdCreateFlag: libc::c_uint {
-        /// Set the close-on-exec ([`FD_CLOEXEC`]) flag on the new file descriptor.
-        ///
-        /// By default, the new file descriptor is set to remain open across an [`execve`]
-        /// (the `FD_CLOEXEC` flag is initially disabled). This flag can be used to change
-        /// this default. The file offset is set to the beginning of the file (see [`lseek`]).
-        ///
-        /// See also the description of the `O_CLOEXEC` flag in [`open(2)`].
-        ///
-        /// [`execve`]: crate::unistd::execve
-        /// [`lseek`]: crate::unistd::lseek
-        /// [`FD_CLOEXEC`]: crate::fcntl::FdFlag::FD_CLOEXEC
-        /// [`open(2)`]: https://man7.org/linux/man-pages/man2/open.2.html
         MFD_CLOEXEC;
-        /// Allow sealing operations on this file.
-        ///
-        /// See also the file sealing notes given in [`memfd_create(2)`].
-        ///
-        /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
         MFD_ALLOW_SEALING;
     }
 );
 
-/// Creates an anonymous file that lives in memory, and return a file-descriptor to it.
-///
-/// The file behaves like a regular file, and so can be modified, truncated, memory-mapped, and so on.
-/// However, unlike a regular file, it lives in RAM and has a volatile backing storage.
-///
-/// For more information, see [`memfd_create(2)`].
-///
-/// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
 pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
     let res = unsafe {
         libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
diff --git a/src/sys/mman.rs b/src/sys/mman.rs
index 0ef1ca8..63a0779 100644
--- a/src/sys/mman.rs
+++ b/src/sys/mman.rs
@@ -1,6 +1,4 @@
-//! Memory management declarations.
-
-use crate::Result;
+use crate::{Error, Result};
 #[cfg(not(target_os = "android"))]
 use crate::NixPath;
 use crate::errno::Errno;
@@ -32,7 +30,7 @@
 }
 
 libc_bitflags!{
-    /// Additional parameters for [`mmap`].
+    /// Additional parameters for `mmap()`.
     pub struct MapFlags: c_int {
         /// Compatibility flag. Ignored.
         MAP_FILE;
@@ -42,13 +40,10 @@
         MAP_PRIVATE;
         /// Place the mapping at exactly the address specified in `addr`.
         MAP_FIXED;
-        /// To be used with `MAP_FIXED`, to forbid the system
-        /// to select a different address than the one specified.
-        #[cfg(target_os = "freebsd")]
-        MAP_EXCL;
         /// Synonym for `MAP_ANONYMOUS`.
         MAP_ANON;
         /// The mapping is not backed by any file.
+        #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
         MAP_ANONYMOUS;
         /// Put the mapping into the first 2GB of the process address space.
         #[cfg(any(all(any(target_os = "android", target_os = "linux"),
@@ -70,8 +65,8 @@
         MAP_LOCKED;
         /// Do not reserve swap space for this mapping.
         ///
-        /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
-        #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd")))]
+        /// This was removed in FreeBSD 11.
+        #[cfg(not(target_os = "freebsd"))]
         MAP_NORESERVE;
         /// Populate page tables for a mapping.
         #[cfg(any(target_os = "android", target_os = "linux"))]
@@ -127,55 +122,39 @@
         MAP_NOSYNC;
         /// Rename private pages to a file.
         ///
-        /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
-        #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
+        /// This was removed in FreeBSD 11.
+        #[cfg(any(target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd"))]
         MAP_RENAME;
         /// Region may contain semaphores.
         #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
         MAP_HASSEMAPHORE;
         /// Region grows down, like a stack.
-        #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))]
+        #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
         MAP_STACK;
         /// Pages in this mapping are not retained in the kernel's memory cache.
         #[cfg(any(target_os = "ios", target_os = "macos"))]
         MAP_NOCACHE;
-        /// Allows the W/X bit on the page, it's necessary on aarch64 architecture.
         #[cfg(any(target_os = "ios", target_os = "macos"))]
         MAP_JIT;
-        /// Allows to use large pages, underlying alignment based on size.
-        #[cfg(target_os = "freebsd")]
-        MAP_ALIGNED_SUPER;
-        /// Pages will be discarded in the core dumps.
-        #[cfg(target_os = "openbsd")]
-        MAP_CONCEAL;
     }
 }
 
-#[cfg(any(target_os = "linux", target_os = "netbsd"))]
+#[cfg(target_os = "linux")]
 libc_bitflags!{
-    /// Options for [`mremap`].
+    /// Options for `mremap()`.
     pub struct MRemapFlags: c_int {
         /// Permit the kernel to relocate the mapping to a new virtual address, if necessary.
-        #[cfg(target_os = "linux")]
         MREMAP_MAYMOVE;
         /// Place the mapping at exactly the address specified in `new_address`.
-        #[cfg(target_os = "linux")]
         MREMAP_FIXED;
-        /// Permits to use the old and new address as hints to relocate the mapping.
-        #[cfg(target_os = "netbsd")]
-        MAP_FIXED;
-        /// Allows to duplicate the mapping to be able to apply different flags on the copy.
-        #[cfg(target_os = "netbsd")]
-        MAP_REMAPDUP;
     }
 }
 
 libc_enum!{
     /// Usage information for a range of memory to allow for performance optimizations by the kernel.
     ///
-    /// Used by [`madvise`].
+    /// Used by [`madvise`](./fn.madvise.html).
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum MmapAdvise {
         /// No further special treatment. This is the default.
         MADV_NORMAL,
@@ -212,8 +191,7 @@
             all(target_os = "linux", any(
                 target_arch = "aarch64",
                 target_arch = "arm",
-                target_arch = "powerpc",
-                target_arch = "powerpc64",
+                target_arch = "ppc",
                 target_arch = "s390x",
                 target_arch = "x86",
                 target_arch = "x86_64",
@@ -266,7 +244,7 @@
 }
 
 libc_bitflags!{
-    /// Configuration flags for [`msync`].
+    /// Configuration flags for `msync`.
     pub struct MsFlags: c_int {
         /// Schedule an update but return immediately.
         MS_ASYNC;
@@ -284,7 +262,7 @@
 }
 
 libc_bitflags!{
-    /// Flags for [`mlockall`].
+    /// Flags for `mlockall`.
     pub struct MlockAllFlags: c_int {
         /// Lock pages that are currently mapped into the address space of the process.
         MCL_CURRENT;
@@ -300,9 +278,7 @@
 ///
 /// # Safety
 ///
-/// `addr` must meet all the requirements described in the [`mlock(2)`] man page.
-///
-/// [`mlock(2)`]: https://man7.org/linux/man-pages/man2/mlock.2.html
+/// `addr` must meet all the requirements described in the `mlock(2)` man page.
 pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
     Errno::result(libc::mlock(addr, length)).map(drop)
 }
@@ -312,28 +288,25 @@
 ///
 /// # Safety
 ///
-/// `addr` must meet all the requirements described in the [`munlock(2)`] man
+/// `addr` must meet all the requirements described in the `munlock(2)` man
 /// page.
-///
-/// [`munlock(2)`]: https://man7.org/linux/man-pages/man2/munlock.2.html
 pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
     Errno::result(libc::munlock(addr, length)).map(drop)
 }
 
 /// Locks all memory pages mapped into this process' address space.
 ///
-/// Locked pages never move to the swap area. For more information, see [`mlockall(2)`].
+/// Locked pages never move to the swap area.
 ///
-/// [`mlockall(2)`]: https://man7.org/linux/man-pages/man2/mlockall.2.html
+/// # Safety
+///
+/// `addr` must meet all the requirements described in the `mlockall(2)` man
+/// page.
 pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
     unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
 }
 
 /// Unlocks all memory pages mapped into this process' address space.
-///
-/// For more information, see [`munlockall(2)`].
-///
-/// [`munlockall(2)`]: https://man7.org/linux/man-pages/man2/munlockall.2.html
 pub fn munlockall() -> Result<()> {
     unsafe { Errno::result(libc::munlockall()) }.map(drop)
 }
@@ -342,14 +315,12 @@
 ///
 /// # Safety
 ///
-/// See the [`mmap(2)`] man page for detailed requirements.
-///
-/// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
+/// See the `mmap(2)` man page for detailed requirements.
 pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> {
     let ret = libc::mmap(addr, length, prot.bits(), flags.bits(), fd, offset);
 
     if ret == libc::MAP_FAILED {
-        Err(Errno::last())
+        Err(Error::Sys(Errno::last()))
     } else {
         Ok(ret)
     }
@@ -362,7 +333,7 @@
 ///
 /// See the `mremap(2)` [man page](https://man7.org/linux/man-pages/man2/mremap.2.html) for
 /// detailed requirements.
-#[cfg(any(target_os = "linux", target_os = "netbsd"))]
+#[cfg(target_os = "linux")]
 pub unsafe fn mremap(
     addr: *mut c_void,
     old_size: size_t,
@@ -370,19 +341,10 @@
     flags: MRemapFlags,
     new_address: Option<* mut c_void>,
 ) -> Result<*mut c_void> {
-    #[cfg(target_os = "linux")]
     let ret = libc::mremap(addr, old_size, new_size, flags.bits(), new_address.unwrap_or(std::ptr::null_mut()));
-    #[cfg(target_os = "netbsd")]
-    let ret = libc::mremap(
-        addr,
-        old_size,
-        new_address.unwrap_or(std::ptr::null_mut()),
-        new_size,
-        flags.bits(),
-        );
 
     if ret == libc::MAP_FAILED {
-        Err(Errno::last())
+        Err(Error::Sys(Errno::last()))
     } else {
         Ok(ret)
     }
@@ -392,10 +354,8 @@
 ///
 /// # Safety
 ///
-/// `addr` must meet all the requirements described in the [`munmap(2)`] man
+/// `addr` must meet all the requirements described in the `munmap(2)` man
 /// page.
-///
-/// [`munmap(2)`]: https://man7.org/linux/man-pages/man2/munmap.2.html
 pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
     Errno::result(libc::munmap(addr, len)).map(drop)
 }
@@ -404,17 +364,15 @@
 ///
 /// # Safety
 ///
-/// See the [`madvise(2)`] man page.  Take special care when using
-/// [`MmapAdvise::MADV_FREE`].
-///
-/// [`madvise(2)`]: https://man7.org/linux/man-pages/man2/madvise.2.html
+/// See the `madvise(2)` man page.  Take special care when using
+/// `MmapAdvise::MADV_FREE`.
 pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) -> Result<()> {
     Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
 }
 
 /// Set protection of memory mapping.
 ///
-/// See [`mprotect(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
+/// See [`mprotect(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
 /// details.
 ///
 /// # Safety
@@ -445,19 +403,12 @@
 ///
 /// # Safety
 ///
-/// `addr` must meet all the requirements described in the [`msync(2)`] man
+/// `addr` must meet all the requirements described in the `msync(2)` man
 /// page.
-///
-/// [`msync(2)`]: https://man7.org/linux/man-pages/man2/msync.2.html
 pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result<()> {
     Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
 }
 
-/// Creates and opens a new, or opens an existing, POSIX shared memory object.
-///
-/// For more information, see [`shm_open(3)`].
-///
-/// [`shm_open(3)`]: https://man7.org/linux/man-pages/man3/shm_open.3.html
 #[cfg(not(target_os = "android"))]
 pub fn shm_open<P: ?Sized + NixPath>(name: &P, flag: OFlag, mode: Mode) -> Result<RawFd> {
     let ret = name.with_nix_path(|cstr| {
@@ -474,11 +425,6 @@
     Errno::result(ret)
 }
 
-/// Performs the converse of [`shm_open`], removing an object previously created.
-///
-/// For more information, see [`shm_unlink(3)`].
-///
-/// [`shm_unlink(3)`]: https://man7.org/linux/man-pages/man3/shm_unlink.3.html
 #[cfg(not(target_os = "android"))]
 pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
     let ret = name.with_nix_path(|cstr| {
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index 156b0d9..02edfd7 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -1,4 +1,3 @@
-//! Mostly platform-specific functionality
 #[cfg(any(target_os = "dragonfly",
           target_os = "freebsd",
           target_os = "ios",
@@ -8,7 +7,6 @@
 pub mod aio;
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
-#[allow(missing_docs)]
 pub mod epoll;
 
 #[cfg(any(target_os = "dragonfly",
@@ -17,11 +15,9 @@
           target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd"))]
-#[allow(missing_docs)]
 pub mod event;
 
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[allow(missing_docs)]
+#[cfg(target_os = "linux")]
 pub mod eventfd;
 
 #[cfg(any(target_os = "android",
@@ -32,7 +28,6 @@
           target_os = "redox",
           target_os = "macos",
           target_os = "netbsd",
-          target_os = "illumos",
           target_os = "openbsd"))]
 #[macro_use]
 pub mod ioctl;
@@ -41,11 +36,9 @@
 pub mod memfd;
 
 #[cfg(not(target_os = "redox"))]
-#[allow(missing_docs)]
 pub mod mman;
 
 #[cfg(target_os = "linux")]
-#[allow(missing_docs)]
 pub mod personality;
 
 pub mod pthread;
@@ -57,19 +50,14 @@
           target_os = "macos",
           target_os = "netbsd",
           target_os = "openbsd"))]
-#[allow(missing_docs)]
 pub mod ptrace;
 
 #[cfg(target_os = "linux")]
 pub mod quota;
 
 #[cfg(any(target_os = "linux"))]
-#[allow(missing_docs)]
 pub mod reboot;
 
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia", target_os = "illumos")))]
-pub mod resource;
-
 #[cfg(not(target_os = "redox"))]
 pub mod select;
 
@@ -83,14 +71,11 @@
 pub mod signal;
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
-#[allow(missing_docs)]
 pub mod signalfd;
 
 #[cfg(not(target_os = "redox"))]
-#[allow(missing_docs)]
 pub mod socket;
 
-#[allow(missing_docs)]
 pub mod stat;
 
 #[cfg(any(target_os = "android",
@@ -106,13 +91,10 @@
 pub mod statvfs;
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
-#[allow(missing_docs)]
 pub mod sysinfo;
 
-#[allow(missing_docs)]
 pub mod termios;
 
-#[allow(missing_docs)]
 pub mod time;
 
 pub mod uio;
@@ -122,9 +104,7 @@
 pub mod wait;
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
-#[allow(missing_docs)]
 pub mod inotify;
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
-#[allow(missing_docs)]
 pub mod timerfd;
diff --git a/src/sys/personality.rs b/src/sys/personality.rs
index b15956c..6548b65 100644
--- a/src/sys/personality.rs
+++ b/src/sys/personality.rs
@@ -39,7 +39,7 @@
         libc::personality(0xFFFFFFFF)
     };
 
-    Errno::result(res).map(Persona::from_bits_truncate)
+    Errno::result(res).map(|r| Persona::from_bits_truncate(r))
 }
 
 /// Set the current process personality.
@@ -66,5 +66,5 @@
         libc::personality(persona.bits() as c_ulong)
     };
 
-    Errno::result(res).map(Persona::from_bits_truncate)
+    Errno::result(res).map(|r| Persona::from_bits_truncate(r))
 }
diff --git a/src/sys/pthread.rs b/src/sys/pthread.rs
index d42e45d..a4d9825 100644
--- a/src/sys/pthread.rs
+++ b/src/sys/pthread.rs
@@ -1,18 +1,9 @@
-//! Low level threading primitives
-
-#[cfg(not(target_os = "redox"))]
-use crate::errno::Errno;
-#[cfg(not(target_os = "redox"))]
-use crate::Result;
-#[cfg(not(target_os = "redox"))]
-use crate::sys::signal::Signal;
 use libc::{self, pthread_t};
 
-/// Identifies an individual thread.
 pub type Pthread = pthread_t;
 
 /// Obtain ID of the calling thread (see
-/// [`pthread_self(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html)
+/// [`pthread_self(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html)
 ///
 /// The thread ID returned by `pthread_self()` is not the same thing as
 /// the kernel thread ID returned by a call to `gettid(2)`.
@@ -20,19 +11,3 @@
 pub fn pthread_self() -> Pthread {
     unsafe { libc::pthread_self() }
 }
-
-/// Send a signal to a thread (see [`pthread_kill(3)`]).
-///
-/// If `signal` is `None`, `pthread_kill` will only preform error checking and
-/// won't send any signal.
-///
-/// [`pthread_kill(3)`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html
-#[cfg(not(target_os = "redox"))]
-pub fn pthread_kill<T: Into<Option<Signal>>>(thread: Pthread, signal: T) -> Result<()> {
-    let sig = match signal.into() {
-        Some(s) => s as libc::c_int,
-        None => 0,
-    };
-    let res = unsafe { libc::pthread_kill(thread, sig) };
-    Errno::result(res).map(drop)
-}
diff --git a/src/sys/ptrace/bsd.rs b/src/sys/ptrace/bsd.rs
index a62881e..e85afc7 100644
--- a/src/sys/ptrace/bsd.rs
+++ b/src/sys/ptrace/bsd.rs
@@ -24,7 +24,6 @@
 libc_enum! {
     #[repr(i32)]
     /// Ptrace Request enum defining the action to be taken.
-    #[non_exhaustive]
     pub enum Request {
         PT_TRACE_ME,
         PT_READ_I,
@@ -134,14 +133,16 @@
 /// use nix::unistd::Pid;
 /// use nix::sys::signal::Signal;
 /// use nix::sys::wait::*;
-/// // If a process changes state to the stopped state because of a SIGUSR1
-/// // signal, this will step the process forward and forward the user
-/// // signal to the stopped process
-/// match waitpid(Pid::from_raw(-1), None) {
-///     Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => {
-///         let _ = step(pid, Signal::SIGUSR1);
+/// fn main() {
+///     // If a process changes state to the stopped state because of a SIGUSR1
+///     // signal, this will step the process forward and forward the user
+///     // signal to the stopped process
+///     match waitpid(Pid::from_raw(-1), None) {
+///         Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => {
+///             let _ = step(pid, Signal::SIGUSR1);
+///         }
+///         _ => {},
 ///     }
-///     _ => {},
 /// }
 /// ```
 #[cfg(
diff --git a/src/sys/ptrace/linux.rs b/src/sys/ptrace/linux.rs
index 3723679..8d1dd16 100644
--- a/src/sys/ptrace/linux.rs
+++ b/src/sys/ptrace/linux.rs
@@ -2,7 +2,7 @@
 
 use cfg_if::cfg_if;
 use std::{mem, ptr};
-use crate::Result;
+use crate::{Error, Result};
 use crate::errno::Errno;
 use libc::{self, c_void, c_long, siginfo_t};
 use crate::unistd::Pid;
@@ -33,7 +33,6 @@
     #[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))]
     #[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))]
     /// Ptrace Request enum defining the action to be taken.
-    #[non_exhaustive]
     pub enum Request {
         PTRACE_TRACEME,
         PTRACE_PEEKTEXT,
@@ -98,9 +97,11 @@
         #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
                                                target_arch = "mips64"))))]
         PTRACE_SETREGSET,
-        #[cfg(target_os = "linux")]
+        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
+                                               target_arch = "mips64"))))]
         PTRACE_SEIZE,
-        #[cfg(target_os = "linux")]
+        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
+                                               target_arch = "mips64"))))]
         PTRACE_INTERRUPT,
         #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
                                                target_arch = "mips64"))))]
@@ -122,7 +123,6 @@
     /// Using the ptrace options the tracer can configure the tracee to stop
     /// at certain events. This enum is used to define those events as defined
     /// in `man ptrace`.
-    #[non_exhaustive]
     pub enum Event {
         /// Event that stops before a return from fork or clone.
         PTRACE_EVENT_FORK,
@@ -137,11 +137,9 @@
         /// Event for a stop before an exit. Unlike the waitpid Exit status program.
         /// registers can still be examined
         PTRACE_EVENT_EXIT,
-        /// Stop triggered by a seccomp rule on a tracee.
+        /// STop triggered by a seccomp rule on a tracee.
         PTRACE_EVENT_SECCOMP,
-        /// Stop triggered by the `INTERRUPT` syscall, or a group stop,
-        /// or when a new child is attached.
-        PTRACE_EVENT_STOP,
+        // PTRACE_EVENT_STOP not provided by libc because it's defined in glibc 2.26
     }
 }
 
@@ -182,7 +180,7 @@
         libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
     };
     match Errno::result(ret) {
-        Ok(..) | Err(Errno::UnknownErrno) => Ok(ret),
+        Ok(..) | Err(Error::Sys(Errno::UnknownErrno)) => Ok(ret),
         err @ Err(..) => err,
     }
 }
@@ -339,7 +337,7 @@
 /// Attach to a running process, as with `ptrace(PTRACE_SEIZE, ...)`
 ///
 /// Attaches to the process specified in pid, making it a tracee of the calling process.
-#[cfg(target_os = "linux")]
+#[cfg(all(target_os = "linux", not(any(target_arch = "mips", target_arch = "mips64"))))]
 pub fn seize(pid: Pid, options: Options) -> Result<()> {
     unsafe {
         ptrace_other(
@@ -384,16 +382,6 @@
     }
 }
 
-/// Stop a tracee, as with `ptrace(PTRACE_INTERRUPT, ...)`
-///
-/// This request is equivalent to `ptrace(PTRACE_INTERRUPT, ...)`
-#[cfg(target_os = "linux")]
-pub fn interrupt(pid: Pid) -> Result<()> {
-    unsafe {
-        ptrace_other(Request::PTRACE_INTERRUPT, pid, ptr::null_mut(), ptr::null_mut()).map(drop)
-    }
-}
-
 /// Issues a kill request as with `ptrace(PTRACE_KILL, ...)`
 ///
 /// This request is equivalent to `ptrace(PTRACE_CONT, ..., SIGKILL);`
@@ -403,7 +391,7 @@
     }
 }
 
-/// Move the stopped tracee process forward by a single step as with
+/// Move the stopped tracee process forward by a single step as with 
 /// `ptrace(PTRACE_SINGLESTEP, ...)`
 ///
 /// Advances the execution of the process with PID `pid` by a single step optionally delivering a
@@ -413,17 +401,18 @@
 /// ```rust
 /// use nix::sys::ptrace::step;
 /// use nix::unistd::Pid;
-/// use nix::sys::signal::Signal;
+/// use nix::sys::signal::Signal; 
 /// use nix::sys::wait::*;
-///
-/// // If a process changes state to the stopped state because of a SIGUSR1
-/// // signal, this will step the process forward and forward the user
-/// // signal to the stopped process
-/// match waitpid(Pid::from_raw(-1), None) {
-///     Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => {
-///         let _ = step(pid, Signal::SIGUSR1);
+/// fn main() {
+///     // If a process changes state to the stopped state because of a SIGUSR1 
+///     // signal, this will step the process forward and forward the user 
+///     // signal to the stopped process
+///     match waitpid(Pid::from_raw(-1), None) {
+///         Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => {
+///             let _ = step(pid, Signal::SIGUSR1);
+///         }
+///         _ => {},
 ///     }
-///     _ => {},
 /// }
 /// ```
 pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
diff --git a/src/sys/quota.rs b/src/sys/quota.rs
index 6e34e38..1933013 100644
--- a/src/sys/quota.rs
+++ b/src/sys/quota.rs
@@ -42,7 +42,6 @@
 libc_enum!{
     /// The scope of the quota.
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum QuotaType {
         /// Specify a user quota
         USRQUOTA,
@@ -54,7 +53,6 @@
 libc_enum!{
     /// The type of quota format to use.
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum QuotaFmt {
         /// Use the original quota format.
         QFMT_VFS_OLD,
diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs
index 46ab68b..e319130 100644
--- a/src/sys/reboot.rs
+++ b/src/sys/reboot.rs
@@ -1,7 +1,8 @@
 //! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
 
-use crate::Result;
+use crate::{Error, Result};
 use crate::errno::Errno;
+use libc;
 use std::convert::Infallible;
 use std::mem::drop;
 
@@ -11,7 +12,6 @@
     /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
     /// enabling/disabling Ctrl-Alt-Delete.
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum RebootMode {
         RB_HALT_SYSTEM,
         RB_KEXEC,
@@ -26,7 +26,7 @@
     unsafe {
         libc::reboot(how as libc::c_int)
     };
-    Err(Errno::last())
+    Err(Error::Sys(Errno::last()))
 }
 
 /// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
diff --git a/src/sys/resource.rs b/src/sys/resource.rs
deleted file mode 100644
index f3bfb67..0000000
--- a/src/sys/resource.rs
+++ /dev/null
@@ -1,233 +0,0 @@
-//! Configure the process resource limits.
-use cfg_if::cfg_if;
-
-use crate::errno::Errno;
-use crate::Result;
-pub use libc::rlim_t;
-use std::mem;
-
-cfg_if! {
-    if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
-        use libc::{__rlimit_resource_t, rlimit, RLIM_INFINITY};
-    }else if #[cfg(any(
-        target_os = "freebsd",
-        target_os = "openbsd",
-        target_os = "netbsd",
-        target_os = "macos",
-        target_os = "ios",
-        target_os = "android",
-        target_os = "dragonfly",
-        all(target_os = "linux", not(target_env = "gnu"))
-    ))]{
-        use libc::{c_int, rlimit, RLIM_INFINITY};
-    }
-}
-
-libc_enum! {
-    /// The Resource enum is platform dependent. Check different platform
-    /// manuals for more details. Some platform links has been provided for
-    /// earier reference (non-exhaustive).
-    ///
-    /// * [Linux](https://man7.org/linux/man-pages/man2/getrlimit.2.html)
-    /// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=setrlimit)
-
-    // linux-gnu uses u_int as resource enum, which is implemented in libc as
-    // well.
-    //
-    // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html
-    // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs
-    #[cfg_attr(all(target_os = "linux", target_env = "gnu"), repr(u32))]
-    #[cfg_attr(any(
-            target_os = "freebsd",
-            target_os = "openbsd",
-            target_os = "netbsd",
-            target_os = "macos",
-            target_os = "ios",
-            target_os = "android",
-            target_os = "dragonfly",
-            all(target_os = "linux", not(target_env = "gnu"))
-        ), repr(i32))]
-    #[non_exhaustive]
-    pub enum Resource {
-        #[cfg(not(any(
-                    target_os = "freebsd",
-                    target_os = "netbsd",
-                    target_os = "openbsd"
-        )))]
-        /// The maximum amount (in bytes) of virtual memory the process is
-        /// allowed to map.
-        RLIMIT_AS,
-        /// The largest size (in bytes) core(5) file that may be created.
-        RLIMIT_CORE,
-        /// The maximum amount of cpu time (in seconds) to be used by each
-        /// process.
-        RLIMIT_CPU,
-        /// The maximum size (in bytes) of the data segment for a process
-        RLIMIT_DATA,
-        /// The largest size (in bytes) file that may be created.
-        RLIMIT_FSIZE,
-        /// The maximum number of open files for this process.
-        RLIMIT_NOFILE,
-        /// The maximum size (in bytes) of the stack segment for a process.
-        RLIMIT_STACK,
-
-        #[cfg(target_os = "freebsd")]
-        /// The maximum number of kqueues this user id is allowed to create.
-        RLIMIT_KQUEUES,
-
-        #[cfg(any(target_os = "android", target_os = "linux"))]
-        /// A limit on the combined number of flock locks and fcntl leases that
-        /// this process may establish.
-        RLIMIT_LOCKS,
-
-        #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
-        /// The maximum size (in bytes) which a process may lock into memory
-        /// using the mlock(2) system call.
-        RLIMIT_MEMLOCK,
-
-        #[cfg(any(target_os = "android", target_os = "linux"))]
-        /// A limit on the number of bytes that can be allocated for POSIX
-        /// message queues  for  the  real  user  ID  of  the  calling process.
-        RLIMIT_MSGQUEUE,
-
-        #[cfg(any(target_os = "android", target_os = "linux"))]
-        /// A ceiling to which the process's nice value can be raised using
-        /// setpriority or nice.
-        RLIMIT_NICE,
-
-        #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
-        /// The maximum number of simultaneous processes for this user id.
-        RLIMIT_NPROC,
-
-        #[cfg(target_os = "freebsd")]
-        /// The maximum number of pseudo-terminals this user id is allowed to
-        /// create.
-        RLIMIT_NPTS,
-
-        #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
-        /// When there is memory pressure and swap is available, prioritize
-        /// eviction of a process' resident pages beyond this amount (in bytes).
-        RLIMIT_RSS,
-
-        #[cfg(any(target_os = "android", target_os = "linux"))]
-        /// A ceiling on the real-time priority that may be set for this process
-        /// using sched_setscheduler and  sched_set‐ param.
-        RLIMIT_RTPRIO,
-
-        #[cfg(any(target_os = "linux"))]
-        /// A limit (in microseconds) on the amount of CPU time that a process
-        /// scheduled under a real-time scheduling policy may con‐ sume without
-        /// making a blocking system call.
-        RLIMIT_RTTIME,
-
-        #[cfg(any(target_os = "android", target_os = "linux"))]
-        /// A limit on the number of signals that may be queued for the real
-        /// user ID of the  calling  process.
-        RLIMIT_SIGPENDING,
-
-        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-        /// The maximum size (in bytes) of socket buffer usage for this user.
-        RLIMIT_SBSIZE,
-
-        #[cfg(target_os = "freebsd")]
-        /// The maximum size (in bytes) of the swap space that may be reserved
-        /// or used by all of this user id's processes.
-        RLIMIT_SWAP,
-
-        #[cfg(target_os = "freebsd")]
-        /// An alias for RLIMIT_AS.
-        RLIMIT_VMEM,
-    }
-}
-
-/// Get the current processes resource limits
-///
-/// A value of `None` indicates the value equals to `RLIM_INFINITY` which means
-/// there is no limit.
-///
-/// # Parameters
-///
-/// * `resource`: The [`Resource`] that we want to get the limits of.
-///
-/// # Examples
-///
-/// ```
-/// # use nix::sys::resource::{getrlimit, Resource};
-///
-/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
-/// println!("current soft_limit: {:?}", soft_limit);
-/// println!("current hard_limit: {:?}", hard_limit);
-/// ```
-///
-/// # References
-///
-/// [getrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
-///
-/// [`Resource`]: enum.Resource.html
-pub fn getrlimit(resource: Resource) -> Result<(Option<rlim_t>, Option<rlim_t>)> {
-    let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();
-
-    cfg_if! {
-        if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
-            let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
-        }else{
-            let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
-        }
-    }
-
-    Errno::result(res).map(|_| {
-        let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() };
-        (Some(rlim_cur), Some(rlim_max))
-    })
-}
-
-/// Set the current processes resource limits
-///
-/// # Parameters
-///
-/// * `resource`: The [`Resource`] that we want to set the limits of.
-/// * `soft_limit`: The value that the kernel enforces for the corresponding
-///   resource. Note: `None` input will be replaced by constant `RLIM_INFINITY`.
-/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to
-///   the current hard limit for non-root users. Note: `None` input will be
-///   replaced by constant `RLIM_INFINITY`.
-///
-/// > Note: for some os (linux_gnu), setting hard_limit to `RLIM_INFINITY` can
-/// > results `EPERM` Error. So you will need to set the number explicitly.
-///
-/// # Examples
-///
-/// ```
-/// # use nix::sys::resource::{setrlimit, Resource};
-///
-/// let soft_limit = Some(512);
-/// let hard_limit = Some(1024);
-/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
-/// ```
-///
-/// # References
-///
-/// [setrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215)
-///
-/// [`Resource`]: enum.Resource.html
-///
-/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`.
-pub fn setrlimit(
-    resource: Resource,
-    soft_limit: Option<rlim_t>,
-    hard_limit: Option<rlim_t>,
-) -> Result<()> {
-    let new_rlim = rlimit {
-        rlim_cur: soft_limit.unwrap_or(RLIM_INFINITY),
-        rlim_max: hard_limit.unwrap_or(RLIM_INFINITY),
-    };
-    cfg_if! {
-        if #[cfg(all(target_os = "linux", target_env = "gnu"))]{
-            let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
-        }else{
-            let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
-        }
-    }
-
-    Errno::result(res).map(drop)
-}
diff --git a/src/sys/select.rs b/src/sys/select.rs
index 4d7576a..a576c7e 100644
--- a/src/sys/select.rs
+++ b/src/sys/select.rs
@@ -1,5 +1,3 @@
-//! Portably monitor a group of file descriptors for readiness.
-use std::convert::TryFrom;
 use std::iter::FusedIterator;
 use std::mem;
 use std::ops::Range;
@@ -13,20 +11,11 @@
 
 pub use libc::FD_SETSIZE;
 
-/// Contains a set of file descriptors used by [`select`]
 #[repr(transparent)]
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub struct FdSet(libc::fd_set);
 
-fn assert_fd_valid(fd: RawFd) {
-    assert!(
-        usize::try_from(fd).map_or(false, |fd| fd < FD_SETSIZE),
-        "fd must be in the range 0..FD_SETSIZE",
-    );
-}
-
 impl FdSet {
-    /// Create an empty `FdSet`
     pub fn new() -> FdSet {
         let mut fdset = mem::MaybeUninit::uninit();
         unsafe {
@@ -35,25 +24,18 @@
         }
     }
 
-    /// Add a file descriptor to an `FdSet`
     pub fn insert(&mut self, fd: RawFd) {
-        assert_fd_valid(fd);
         unsafe { libc::FD_SET(fd, &mut self.0) };
     }
 
-    /// Remove a file descriptor from an `FdSet`
     pub fn remove(&mut self, fd: RawFd) {
-        assert_fd_valid(fd);
         unsafe { libc::FD_CLR(fd, &mut self.0) };
     }
 
-    /// Test an `FdSet` for the presence of a certain file descriptor.
-    pub fn contains(&self, fd: RawFd) -> bool {
-        assert_fd_valid(fd);
-        unsafe { libc::FD_ISSET(fd, &self.0) }
+    pub fn contains(&mut self, fd: RawFd) -> bool {
+        unsafe { libc::FD_ISSET(fd, &mut self.0) }
     }
 
-    /// Remove all file descriptors from this `FdSet`.
     pub fn clear(&mut self) {
         unsafe { libc::FD_ZERO(&mut self.0) };
     }
@@ -68,19 +50,21 @@
     ///
     /// ```
     /// # use nix::sys::select::FdSet;
+    /// # fn main() {
     /// let mut set = FdSet::new();
     /// set.insert(4);
     /// set.insert(9);
     /// assert_eq!(set.highest(), Some(9));
+    /// # }
     /// ```
     ///
     /// [`select`]: fn.select.html
-    pub fn highest(&self) -> Option<RawFd> {
+    pub fn highest(&mut self) -> Option<RawFd> {
         self.fds(None).next_back()
     }
 
     /// Returns an iterator over the file descriptors in the set.
-    ///
+    /// 
     /// For performance, it takes an optional higher bound: the iterator will
     /// not return any elements of the set greater than the given file
     /// descriptor.
@@ -97,7 +81,7 @@
     /// assert_eq!(fds, vec![4, 9]);
     /// ```
     #[inline]
-    pub fn fds(&self, highest: Option<RawFd>) -> Fds {
+    pub fn fds(&mut self, highest: Option<RawFd>) -> Fds {
         Fds {
             set: self,
             range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE),
@@ -114,7 +98,7 @@
 /// Iterator over `FdSet`.
 #[derive(Debug)]
 pub struct Fds<'a> {
-    set: &'a FdSet,
+    set: &'a mut FdSet,
     range: Range<usize>,
 }
 
@@ -122,7 +106,7 @@
     type Item = RawFd;
 
     fn next(&mut self) -> Option<RawFd> {
-        for i in &mut self.range {
+        while let Some(i) = self.range.next() {
             if self.set.contains(i as RawFd) {
                 return Some(i as RawFd);
             }
@@ -171,7 +155,7 @@
 ///
 /// # References
 ///
-/// [select(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
+/// [select(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
 ///
 /// [`FdSet::highest`]: struct.FdSet.html#method.highest
 pub fn select<'a, N, R, W, E, T>(nfds: N,
@@ -237,7 +221,7 @@
 ///
 /// # References
 ///
-/// [pselect(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html)
+/// [pselect(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html)
 ///
 /// [The new pselect() system call](https://lwn.net/Articles/176911/)
 ///
diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs
index 7a210c6..84fe2a9 100644
--- a/src/sys/sendfile.rs
+++ b/src/sys/sendfile.rs
@@ -1,5 +1,3 @@
-//! Send data from a file to a socket, bypassing userland.
-
 use cfg_if::cfg_if;
 use std::os::unix::io::RawFd;
 use std::ptr;
@@ -20,7 +18,7 @@
 ///
 /// `in_fd` must support `mmap`-like operations and therefore cannot be a socket.
 ///
-/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
+/// For more information, see [the sendfile(2) man page.](http://man7.org/linux/man-pages/man2/sendfile.2.html)
 #[cfg(any(target_os = "android", target_os = "linux"))]
 pub fn sendfile(
     out_fd: RawFd,
@@ -35,32 +33,6 @@
     Errno::result(ret).map(|r| r as usize)
 }
 
-/// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`.
-///
-/// Returns a `Result` with the number of bytes written.
-///
-/// If `offset` is `None`, `sendfile` will begin reading at the current offset of `in_fd`and will
-/// update the offset of `in_fd`. If `offset` is `Some`, `sendfile` will begin at the specified
-/// offset and will not update the offset of `in_fd`. Instead, it will mutate `offset` to point to
-/// the byte after the last byte copied.
-///
-/// `in_fd` must support `mmap`-like operations and therefore cannot be a socket.
-///
-/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
-#[cfg(target_os = "linux")]
-pub fn sendfile64(
-    out_fd: RawFd,
-    in_fd: RawFd,
-    offset: Option<&mut libc::off64_t>,
-    count: usize,
-) -> Result<usize> {
-    let offset = offset
-        .map(|offset| offset as *mut _)
-        .unwrap_or(ptr::null_mut());
-    let ret = unsafe { libc::sendfile64(out_fd, in_fd, offset, count) };
-    Errno::result(ret).map(|r| r as usize)
-}
-
 cfg_if! {
     if #[cfg(any(target_os = "freebsd",
                  target_os = "ios",
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index 61bdc74..2f8b5fa 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -1,11 +1,12 @@
 // Portions of this file are Copyright 2014 The Rust Project Developers.
-// See https://www.rust-lang.org/policies/licenses.
+// See http://rust-lang.org/COPYRIGHT.
 
-//! Operating system signals.
+///! Operating system signals.
 
 use crate::{Error, Result};
 use crate::errno::Errno;
 use crate::unistd::Pid;
+use std::convert::TryFrom;
 use std::mem;
 use std::fmt;
 use std::str::FromStr;
@@ -17,94 +18,58 @@
 pub use self::sigevent::*;
 
 libc_enum!{
-    /// Types of operating system signals
     // Currently there is only one definition of c_int in libc, as well as only one
     // type for signal constants.
     // We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
     // this is not (yet) possible.
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum Signal {
-        /// Hangup
         SIGHUP,
-        /// Interrupt
         SIGINT,
-        /// Quit
         SIGQUIT,
-        /// Illegal instruction (not reset when caught)
         SIGILL,
-        /// Trace trap (not reset when caught)
         SIGTRAP,
-        /// Abort
         SIGABRT,
-        /// Bus error
         SIGBUS,
-        /// Floating point exception
         SIGFPE,
-        /// Kill (cannot be caught or ignored)
         SIGKILL,
-        /// User defined signal 1
         SIGUSR1,
-        /// Segmentation violation
         SIGSEGV,
-        /// User defined signal 2
         SIGUSR2,
-        /// Write on a pipe with no one to read it
         SIGPIPE,
-        /// Alarm clock
         SIGALRM,
-        /// Software termination signal from kill
         SIGTERM,
-        /// Stack fault (obsolete)
         #[cfg(all(any(target_os = "android", target_os = "emscripten",
                       target_os = "fuchsia", target_os = "linux"),
                   not(any(target_arch = "mips", target_arch = "mips64",
                           target_arch = "sparc64"))))]
         SIGSTKFLT,
-        /// To parent on child stop or exit
         SIGCHLD,
-        /// Continue a stopped process
         SIGCONT,
-        /// Sendable stop signal not from tty
         SIGSTOP,
-        /// Stop signal from tty
         SIGTSTP,
-        /// To readers pgrp upon background tty read
         SIGTTIN,
-        /// Like TTIN if (tp->t_local&LTOSTOP)
         SIGTTOU,
-        /// Urgent condition on IO channel
         SIGURG,
-        /// Exceeded CPU time limit
         SIGXCPU,
-        /// Exceeded file size limit
         SIGXFSZ,
-        /// Virtual time alarm
         SIGVTALRM,
-        /// Profiling time alarm
         SIGPROF,
-        /// Window size changes
         SIGWINCH,
-        /// Input/output possible signal
         SIGIO,
         #[cfg(any(target_os = "android", target_os = "emscripten",
                   target_os = "fuchsia", target_os = "linux"))]
-        /// Power failure imminent.
         SIGPWR,
-        /// Bad system call
         SIGSYS,
         #[cfg(not(any(target_os = "android", target_os = "emscripten",
                       target_os = "fuchsia", target_os = "linux",
                       target_os = "redox")))]
-        /// Emulator trap
         SIGEMT,
         #[cfg(not(any(target_os = "android", target_os = "emscripten",
                       target_os = "fuchsia", target_os = "linux",
                       target_os = "redox")))]
-        /// Information request
         SIGINFO,
     }
-    impl TryFrom<i32>
 }
 
 impl FromStr for Signal {
@@ -156,7 +121,7 @@
                           target_os = "fuchsia", target_os = "linux",
                           target_os = "redox")))]
             "SIGINFO" => Signal::SIGINFO,
-            _ => return Err(Errno::EINVAL),
+            _ => return Err(Error::invalid_argument()),
         })
     }
 }
@@ -167,7 +132,7 @@
     /// This function is equivalent to `<Signal as AsRef<str>>::as_ref()`,
     /// with difference that returned string is `'static`
     /// and not bound to `self`'s lifetime.
-    pub const fn as_str(self) -> &'static str {
+    pub fn as_str(self) -> &'static str {
         match self {
             Signal::SIGHUP => "SIGHUP",
             Signal::SIGINT => "SIGINT",
@@ -369,8 +334,9 @@
     SIGEMT,
     SIGINFO];
 
+pub const NSIG: libc::c_int = 32;
+
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-/// Iterate through all signals defined by this operating system
 pub struct SignalIterator {
     next: usize,
 }
@@ -390,17 +356,25 @@
 }
 
 impl Signal {
-    /// Iterate through all signals defined by this OS
-    pub const fn iterator() -> SignalIterator {
+    pub fn iterator() -> SignalIterator {
         SignalIterator{next: 0}
     }
 }
 
-/// Alias for [`SIGABRT`]
+impl TryFrom<libc::c_int> for Signal {
+    type Error = Error;
+
+    fn try_from(signum: libc::c_int) -> Result<Signal> {
+        if 0 < signum && signum < NSIG {
+            Ok(unsafe { mem::transmute(signum) })
+        } else {
+            Err(Error::invalid_argument())
+        }
+    }
+}
+
 pub const SIGIOT : Signal = SIGABRT;
-/// Alias for [`SIGIO`]
 pub const SIGPOLL : Signal = SIGIO;
-/// Alias for [`SIGSYS`]
 pub const SIGUNUSED : Signal = SIGSYS;
 
 #[cfg(not(target_os = "redox"))]
@@ -409,48 +383,26 @@
 type SaFlags_t = libc::c_ulong;
 
 libc_bitflags!{
-    /// Controls the behavior of a [`SigAction`]
     pub struct SaFlags: SaFlags_t {
-        /// When catching a [`Signal::SIGCHLD`] signal, the signal will be
-        /// generated only when a child process exits, not when a child process
-        /// stops.
         SA_NOCLDSTOP;
-        /// When catching a [`Signal::SIGCHLD`] signal, the system will not
-        /// create zombie processes when children of the calling process exit.
         SA_NOCLDWAIT;
-        /// Further occurrences of the delivered signal are not masked during
-        /// the execution of the handler.
         SA_NODEFER;
-        /// The system will deliver the signal to the process on a signal stack,
-        /// specified by each thread with sigaltstack(2).
         SA_ONSTACK;
-        /// The handler is reset back to the default at the moment the signal is
-        /// delivered.
         SA_RESETHAND;
-        /// Requests that certain system calls restart if interrupted by this
-        /// signal.  See the man page for complete details.
         SA_RESTART;
-        /// This flag is controlled internally by Nix.
         SA_SIGINFO;
     }
 }
 
 libc_enum! {
-    /// Specifies how certain functions should manipulate a signal mask
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum SigmaskHow {
-        /// The new mask is the union of the current mask and the specified set.
         SIG_BLOCK,
-        /// The new mask is the intersection of the current mask and the
-        /// complement of the specified set.
         SIG_UNBLOCK,
-        /// The current mask is replaced by the specified set.
         SIG_SETMASK,
     }
 }
 
-/// Specifies a set of [`Signal`]s that may be blocked, waited for, etc.
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub struct SigSet {
     sigset: libc::sigset_t
@@ -458,7 +410,6 @@
 
 
 impl SigSet {
-    /// Initialize to include all signals.
     pub fn all() -> SigSet {
         let mut sigset = mem::MaybeUninit::uninit();
         let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
@@ -466,7 +417,6 @@
         unsafe{ SigSet { sigset: sigset.assume_init() } }
     }
 
-    /// Initialize to include nothing.
     pub fn empty() -> SigSet {
         let mut sigset = mem::MaybeUninit::uninit();
         let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
@@ -474,22 +424,18 @@
         unsafe{ SigSet { sigset: sigset.assume_init() } }
     }
 
-    /// Add the specified signal to the set.
     pub fn add(&mut self, signal: Signal) {
         unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
     }
 
-    /// Remove all signals from this set.
     pub fn clear(&mut self) {
         unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
     }
 
-    /// Remove the specified signal from this set.
     pub fn remove(&mut self, signal: Signal) {
         unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
     }
 
-    /// Return whether this set includes the specified signal.
     pub fn contains(&self, signal: Signal) -> bool {
         let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
 
@@ -500,8 +446,6 @@
         }
     }
 
-    /// Merge all of `other`'s signals into this set.
-    // TODO: use libc::sigorset on supported operating systems.
     pub fn extend(&mut self, other: &SigSet) {
         for signal in Signal::iterator() {
             if other.contains(signal) {
@@ -543,8 +487,6 @@
     /// signal mask becomes pending, and returns the accepted signal.
     #[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
     pub fn wait(&self) -> Result<Signal> {
-        use std::convert::TryFrom;
-
         let mut signum = mem::MaybeUninit::uninit();
         let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
 
@@ -640,31 +582,9 @@
         match self.sigaction.sa_sigaction {
             libc::SIG_DFL => SigHandler::SigDfl,
             libc::SIG_IGN => SigHandler::SigIgn,
-            p if self.flags().contains(SaFlags::SA_SIGINFO) =>
-                SigHandler::SigAction(
-                // Safe for one of two reasons:
-                // * The SigHandler was created by SigHandler::new, in which
-                //   case the pointer is correct, or
-                // * The SigHandler was created by signal or sigaction, which
-                //   are unsafe functions, so the caller should've somehow
-                //   ensured that it is correctly initialized.
-                unsafe{
-                    *(&p as *const usize
-                         as *const extern fn(_, _, _))
-                }
-                as extern fn(_, _, _)),
-            p => SigHandler::Handler(
-                // Safe for one of two reasons:
-                // * The SigHandler was created by SigHandler::new, in which
-                //   case the pointer is correct, or
-                // * The SigHandler was created by signal or sigaction, which
-                //   are unsafe functions, so the caller should've somehow
-                //   ensured that it is correctly initialized.
-                unsafe{
-                    *(&p as *const usize
-                         as *const extern fn(libc::c_int))
-                }
-                as extern fn(libc::c_int)),
+            f if self.flags().contains(SaFlags::SA_SIGINFO) =>
+                SigHandler::SigAction( unsafe { mem::transmute(f) } ),
+            f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
         }
     }
 
@@ -674,18 +594,7 @@
         match self.sigaction.sa_handler {
             libc::SIG_DFL => SigHandler::SigDfl,
             libc::SIG_IGN => SigHandler::SigIgn,
-            p => SigHandler::Handler(
-                // Safe for one of two reasons:
-                // * The SigHandler was created by SigHandler::new, in which
-                //   case the pointer is correct, or
-                // * The SigHandler was created by signal or sigaction, which
-                //   are unsafe functions, so the caller should've somehow
-                //   ensured that it is correctly initialized.
-                unsafe{
-                    *(&p as *const usize
-                         as *const extern fn(libc::c_int))
-                }
-                as extern fn(libc::c_int)),
+            f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
         }
     }
 }
@@ -697,16 +606,9 @@
 ///
 /// # Safety
 ///
-/// * Signal handlers may be called at any point during execution, which limits
-///   what is safe to do in the body of the signal-catching function. Be certain
-///   to only make syscalls that are explicitly marked safe for signal handlers
-///   and only share global data using atomics.
-///
-/// * There is also no guarantee that the old signal handler was installed
-///   correctly.  If it was installed by this crate, it will be.  But if it was
-///   installed by, for example, C code, then there is no guarantee its function
-///   pointer is valid.  In that case, this function effectively dereferences a
-///   raw pointer of unknown provenance.
+/// Signal handlers may be called at any point during execution, which limits what is safe to do in
+/// the body of the signal-catching function. Be certain to only make syscalls that are explicitly
+/// marked safe for signal handlers and only share global data using atomics.
 pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
     let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
 
@@ -717,7 +619,7 @@
     Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
 }
 
-/// Signal management (see [signal(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
+/// Signal management (see [signal(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
 ///
 /// Installs `handler` for the given `signal`, returning the previous signal
 /// handler. `signal` should only be used following another call to `signal` or
@@ -762,7 +664,7 @@
 ///
 /// # Errors
 ///
-/// Returns [`Error(Errno::EOPNOTSUPP)`] if `handler` is
+/// Returns [`Error::UnsupportedOperation`] if `handler` is
 /// [`SigAction`][SigActionStruct]. Use [`sigaction`][SigActionFn] instead.
 ///
 /// `signal` also returns any error from `libc::signal`, such as when an attempt
@@ -779,16 +681,13 @@
         SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
         SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
         #[cfg(not(target_os = "redox"))]
-        SigHandler::SigAction(_) => return Err(Errno::ENOTSUP),
+        SigHandler::SigAction(_) => return Err(Error::UnsupportedOperation),
     };
     Errno::result(res).map(|oldhandler| {
         match oldhandler {
             libc::SIG_DFL => SigHandler::SigDfl,
             libc::SIG_IGN => SigHandler::SigIgn,
-            p => SigHandler::Handler(
-                *(&p as *const usize
-                     as *const extern fn(libc::c_int))
-                as extern fn(libc::c_int)),
+            f => SigHandler::Handler(mem::transmute(f)),
         }
     })
 }
@@ -825,8 +724,8 @@
 ///
 /// If both `set` and `oldset` is None, this function is a no-op.
 ///
-/// For more information, visit the [`pthread_sigmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html),
-/// or [`sigprocmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
+/// For more information, visit the [`pthread_sigmask`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html),
+/// or [`sigprocmask`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
 pub fn pthread_sigmask(how: SigmaskHow,
                        set: Option<&SigSet>,
                        oldset: Option<&mut SigSet>) -> Result<()>
@@ -837,7 +736,7 @@
 /// Examine and change blocked signals.
 ///
 /// For more informations see the [`sigprocmask` man
-/// pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
+/// pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
 pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
     if set.is_none() && oldset.is_none() {
         return Ok(())
@@ -855,24 +754,6 @@
     Errno::result(res).map(drop)
 }
 
-/// Send a signal to a process
-///
-/// # Arguments
-///
-/// * `pid` -    Specifies which processes should receive the signal.
-///   - If positive, specifies an individual process
-///   - If zero, the signal will be sent to all processes whose group
-///     ID is equal to the process group ID of the sender.  This is a
-///     variant of [`killpg`].
-///   - If `-1` and the process has super-user privileges, the signal
-///     is sent to all processes exclusing system processes.
-///   - If less than `-1`, the signal is sent to all processes whose
-///     process group ID is equal to the absolute value of `pid`.
-/// * `signal` - Signal to send. If `None`, error checking is performed
-///              but no signal is actually sent.
-///
-/// See Also
-/// [`kill(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html)
 pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
     let res = unsafe { libc::kill(pid.into(),
                                   match signal.into() {
@@ -883,16 +764,12 @@
     Errno::result(res).map(drop)
 }
 
-/// Send a signal to a process group
+/// Send a signal to a process group [(see
+/// killpg(3))](http://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
 ///
-/// # Arguments
-///
-/// * `pgrp` -   Process group to signal.  If less then or equal 1, the behavior
-///              is platform-specific.
-/// * `signal` - Signal to send. If `None`, `killpg` will only preform error
-///              checking and won't send any signal.
-///
-/// See Also [killpg(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
+/// If `pgrp` less then or equal 1, the behavior is platform-specific.
+/// If `signal` is `None`, `killpg` will only preform error checking and won't
+/// send any signal.
 #[cfg(not(target_os = "fuchsia"))]
 pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
     let res = unsafe { libc::killpg(pgrp.into(),
@@ -904,9 +781,6 @@
     Errno::result(res).map(drop)
 }
 
-/// Send a signal to the current thread
-///
-/// See Also [raise(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html)
 pub fn raise(signal: Signal) -> Result<()> {
     let res = unsafe { libc::raise(signal as libc::c_int) };
 
@@ -914,51 +788,36 @@
 }
 
 
-/// Identifies a thread for [`SigevNotify::SigevThreadId`]
 #[cfg(target_os = "freebsd")]
 pub type type_of_thread_id = libc::lwpid_t;
-/// Identifies a thread for [`SigevNotify::SigevThreadId`]
 #[cfg(target_os = "linux")]
 pub type type_of_thread_id = libc::pid_t;
 
-/// Specifies the notification method used by a [`SigEvent`]
+/// Used to request asynchronous notification of certain events, for example,
+/// with POSIX AIO, POSIX message queues, and POSIX timers.
 // sigval is actually a union of a int and a void*.  But it's never really used
 // as a pointer, because neither libc nor the kernel ever dereference it.  nix
 // therefore presents it as an intptr_t, which is how kevent uses it.
-#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub enum SigevNotify {
     /// No notification will be delivered
     SigevNone,
-    /// Notify by delivering a signal to the process.
-    SigevSignal {
-        /// Signal to deliver
-        signal: Signal,
-        /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
-        /// structure of the queued signal.
-        si_value: libc::intptr_t
-    },
+    /// The signal given by `signal` will be delivered to the process.  The
+    /// value in `si_value` will be present in the `si_value` field of the
+    /// `siginfo_t` structure of the queued signal.
+    SigevSignal { signal: Signal, si_value: libc::intptr_t },
     // Note: SIGEV_THREAD is not implemented because libc::sigevent does not
     // expose a way to set the union members needed by SIGEV_THREAD.
-    /// Notify by delivering an event to a kqueue.
+    /// A new `kevent` is posted to the kqueue `kq`.  The `kevent`'s `udata`
+    /// field will contain the value in `udata`.
     #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-    SigevKevent {
-        /// File descriptor of the kqueue to notify.
-        kq: RawFd,
-        /// Will be contained in the kevent's `udata` field.
-        udata: libc::intptr_t
-    },
-    /// Notify by delivering a signal to a thread.
+    SigevKevent { kq: RawFd, udata: libc::intptr_t },
+    /// The signal `signal` is queued to the thread whose LWP ID is given in
+    /// `thread_id`.  The value stored in `si_value` will be present in the
+    /// `si_value` of the `siginfo_t` structure of the queued signal.
     #[cfg(any(target_os = "freebsd", target_os = "linux"))]
-    SigevThreadId {
-        /// Signal to send
-        signal: Signal,
-        /// LWP ID of the thread to notify
-        thread_id: type_of_thread_id,
-        /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
-        /// structure of the queued signal.
-        si_value: libc::intptr_t
-    },
+    SigevThreadId { signal: Signal, thread_id: type_of_thread_id,
+                    si_value: libc::intptr_t },
 }
 
 #[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
@@ -991,10 +850,10 @@
         /// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or
         /// `SIGEV_SIGNAL`.  That field is part of a union that shares space with the
         /// more genuinely useful `sigev_notify_thread_id`
-        // Allow invalid_value warning on Fuchsia only.
-        // See https://github.com/nix-rust/nix/issues/1441
-        #[cfg_attr(target_os = "fuchsia", allow(invalid_value))]
         pub fn new(sigev_notify: SigevNotify) -> SigEvent {
+            // NB: This uses MaybeUninit rather than mem::zeroed because libc::sigevent contains a
+            // function pointer on Fuchsia as of https://github.com/rust-lang/libc/commit/2f59370,
+            // and function pointers must not be null.
             let mut sev = unsafe { mem::MaybeUninit::<libc::sigevent>::zeroed().assume_init() };
             sev.sigev_notify = match sigev_notify {
                 SigevNotify::SigevNone => libc::SIGEV_NONE,
@@ -1040,7 +899,6 @@
         fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
         }
 
-        /// Return a copy of the inner structure
         pub fn sigevent(&self) -> libc::sigevent {
             self.sigevent
         }
@@ -1091,7 +949,7 @@
 
     #[test]
     fn test_from_str_invalid_value() {
-        let errval = Err(Errno::EINVAL);
+        let errval = Err(Error::Sys(Errno::EINVAL));
         assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
         assert_eq!("kill".parse::<Signal>(), errval);
         assert_eq!("9".parse::<Signal>(), errval);
diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs
index bc4a452..c43b450 100644
--- a/src/sys/signalfd.rs
+++ b/src/sys/signalfd.rs
@@ -15,8 +15,9 @@
 //!
 //! Please note that signal discarding is not specific to `signalfd`, but also happens with regular
 //! signal handlers.
+use libc;
 use crate::unistd;
-use crate::Result;
+use crate::{Error, Result};
 use crate::errno::Errno;
 pub use crate::sys::signal::{self, SigSet};
 pub use libc::signalfd_siginfo as siginfo;
@@ -33,8 +34,7 @@
 }
 
 pub const SIGNALFD_NEW: RawFd = -1;
-#[deprecated(since = "0.23.0", note = "use mem::size_of::<siginfo>() instead")]
-pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>();
+pub const SIGNALFD_SIGINFO_SIZE: usize = 128;
 
 /// Creates a new file descriptor for reading signals.
 ///
@@ -46,7 +46,7 @@
 /// A signal must be blocked on every thread in a process, otherwise it won't be visible from
 /// signalfd (the default handler will be invoked instead).
 ///
-/// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html)
+/// See [the signalfd man page for more information](http://man7.org/linux/man-pages/man2/signalfd.2.html)
 pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
     unsafe {
         Errno::result(libc::signalfd(fd as libc::c_int, mask.as_ref(), flags.bits()))
@@ -98,16 +98,17 @@
     }
 
     pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
-        let mut buffer = mem::MaybeUninit::<siginfo>::uninit();
+        let mut buffer = mem::MaybeUninit::<[u8; SIGNALFD_SIGINFO_SIZE]>::uninit();
 
-        let size = mem::size_of_val(&buffer);
         let res = Errno::result(unsafe {
-            libc::read(self.0, buffer.as_mut_ptr() as *mut libc::c_void, size)
+            libc::read(self.0,
+                       buffer.as_mut_ptr() as *mut libc::c_void,
+                       SIGNALFD_SIGINFO_SIZE as libc::size_t)
         }).map(|r| r as usize);
         match res {
-            Ok(x) if x == size => Ok(Some(unsafe { buffer.assume_init() })),
+            Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer.assume_init()) })),
             Ok(_) => unreachable!("partial read on signalfd"),
-            Err(Errno::EAGAIN) => Ok(None),
+            Err(Error::Sys(Errno::EAGAIN)) => Ok(None),
             Err(error) => Err(error)
         }
     }
@@ -116,7 +117,7 @@
 impl Drop for SignalFd {
     fn drop(&mut self) {
         let e = unistd::close(self.0);
-        if !std::thread::panicking() && e == Err(Errno::EBADF) {
+        if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
             panic!("Closing an invalid file descriptor!");
         };
     }
@@ -143,6 +144,14 @@
 #[cfg(test)]
 mod tests {
     use super::*;
+    use std::mem;
+    use libc;
+
+
+    #[test]
+    fn check_siginfo_size() {
+        assert_eq!(mem::size_of::<libc::signalfd_siginfo>(), SIGNALFD_SIGINFO_SIZE);
+    }
 
     #[test]
     fn create_signalfd() {
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index b119642..2299c57 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -1,7 +1,6 @@
 use super::sa_family_t;
-use crate::{Result, NixPath};
+use crate::{Error, Result, NixPath};
 use crate::errno::Errno;
-use memoffset::offset_of;
 use std::{fmt, mem, net, ptr, slice};
 use std::ffi::OsStr;
 use std::hash::{Hash, Hasher};
@@ -21,7 +20,6 @@
           target_os = "ios",
           target_os = "linux",
           target_os = "macos",
-          target_os = "illumos",
           target_os = "netbsd",
           target_os = "openbsd",
           target_os = "fuchsia"))]
@@ -32,24 +30,19 @@
 /// These constants specify the protocol family to be used
 /// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
 #[repr(i32)]
-#[non_exhaustive]
 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
 pub enum AddressFamily {
-    /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html))
+    /// Local communication (see [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html))
     Unix = libc::AF_UNIX,
-    /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html))
+    /// IPv4 Internet protocols (see [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html))
     Inet = libc::AF_INET,
-    /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html))
+    /// IPv6 Internet protocols (see [`ipv6(7)`](http://man7.org/linux/man-pages/man7/ipv6.7.html))
     Inet6 = libc::AF_INET6,
-    /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
+    /// Kernel user interface device (see [`netlink(7)`](http://man7.org/linux/man-pages/man7/netlink.7.html))
     #[cfg(any(target_os = "android", target_os = "linux"))]
     Netlink = libc::AF_NETLINK,
-    /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html))
-    #[cfg(any(target_os = "android",
-              target_os = "linux",
-              target_os = "illumos",
-              target_os = "fuchsia",
-              target_os = "solaris"))]
+    /// Low level packet interface (see [`packet(7)`](http://man7.org/linux/man-pages/man7/packet.7.html))
+    #[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
     Packet = libc::AF_PACKET,
     /// KEXT Controls and Notifications
     #[cfg(any(target_os = "ios", target_os = "macos"))]
@@ -68,7 +61,7 @@
     /// Access to raw ATM PVCs
     #[cfg(any(target_os = "android", target_os = "linux"))]
     AtmPvc = libc::AF_ATMPVC,
-    /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html))
+    /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](http://man7.org/linux/man-pages/man7/x25.7.html))
     #[cfg(any(target_os = "android", target_os = "linux"))]
     X25 = libc::AF_X25,
     #[cfg(any(target_os = "android", target_os = "linux"))]
@@ -105,16 +98,12 @@
     Can = libc::AF_CAN,
     #[cfg(any(target_os = "android", target_os = "linux"))]
     Tipc = libc::AF_TIPC,
-    #[cfg(not(any(target_os = "illumos",
-                  target_os = "ios",
-                  target_os = "macos",
-                  target_os = "solaris")))]
+    #[cfg(not(any(target_os = "ios", target_os = "macos")))]
     Bluetooth = libc::AF_BLUETOOTH,
     #[cfg(any(target_os = "android", target_os = "linux"))]
     Iucv = libc::AF_IUCV,
     #[cfg(any(target_os = "android", target_os = "linux"))]
     RxRpc = libc::AF_RXRPC,
-    #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
     Isdn = libc::AF_ISDN,
     #[cfg(any(target_os = "android", target_os = "linux"))]
     Phonet = libc::AF_PHONET,
@@ -201,7 +190,6 @@
               target_os = "freebsd",
               target_os = "ios",
               target_os = "macos",
-              target_os = "illumos",
               target_os = "netbsd",
               target_os = "openbsd"))]
     Link = libc::AF_LINK,
@@ -226,7 +214,7 @@
               target_os = "netbsd",
               target_os = "openbsd"))]
     Natm = libc::AF_NATM,
-    /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
+    /// Unspecified address family, (see [`getaddrinfo(3)`](http://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
     #[cfg(any(target_os = "android", target_os = "linux"))]
     Unspec = libc::AF_UNSPEC,
 }
@@ -237,7 +225,7 @@
     ///
     /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
     /// and System. Returns None for unsupported or unknown address families.
-    pub const fn from_i32(family: i32) -> Option<AddressFamily> {
+    pub fn from_i32(family: i32) -> Option<AddressFamily> {
         match family {
             libc::AF_UNIX => Some(AddressFamily::Unix),
             libc::AF_INET => Some(AddressFamily::Inet),
@@ -253,7 +241,6 @@
                       target_os = "ios",
                       target_os = "macos",
                       target_os = "netbsd",
-                      target_os = "illumos",
                       target_os = "openbsd"))]
             libc::AF_LINK => Some(AddressFamily::Link),
             #[cfg(any(target_os = "android", target_os = "linux"))]
@@ -270,7 +257,6 @@
 }
 
 impl InetAddr {
-    #[allow(clippy::needless_update)]   // It isn't needless on all OSes
     pub fn from_std(std: &net::SocketAddr) -> InetAddr {
         match *std {
             net::SocketAddr::V4(ref addr) => {
@@ -294,7 +280,6 @@
         }
     }
 
-    #[allow(clippy::needless_update)]   // It isn't needless on all OSes
     pub fn new(ip: IpAddr, port: u16) -> InetAddr {
         match ip {
             IpAddr::V4(ref ip) => {
@@ -316,7 +301,7 @@
         }
     }
     /// Gets the IP address associated with this socket address.
-    pub const fn ip(&self) -> IpAddr {
+    pub fn ip(&self) -> IpAddr {
         match *self {
             InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
             InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
@@ -324,7 +309,7 @@
     }
 
     /// Gets the port number associated with this socket address
-    pub const fn port(&self) -> u16 {
+    pub fn port(&self) -> u16 {
         match *self {
             InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
             InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
@@ -346,7 +331,6 @@
         }
     }
 
-    #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
     pub fn to_str(&self) -> String {
         format!("{}", self)
     }
@@ -376,7 +360,7 @@
     /// Create a new IpAddr that contains an IPv4 address.
     ///
     /// The result will represent the IP address a.b.c.d
-    pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
+    pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
         IpAddr::V4(Ipv4Addr::new(a, b, c, d))
     }
 
@@ -385,7 +369,7 @@
     /// The result will represent the IP address a:b:c:d:e:f
     #[allow(clippy::many_single_char_names)]
     #[allow(clippy::too_many_arguments)]
-    pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
+    pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
         IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
     }
 
@@ -396,7 +380,7 @@
         }
     }
 
-    pub const fn to_std(&self) -> net::IpAddr {
+    pub fn to_std(&self) -> net::IpAddr {
         match *self {
             IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
             IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
@@ -424,11 +408,11 @@
 
 impl Ipv4Addr {
     #[allow(clippy::identity_op)]   // More readable this way
-    pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
-        let ip = (((a as u32) << 24) |
-                  ((b as u32) << 16) |
-                  ((c as u32) <<  8) |
-                  ((d as u32) <<  0)).to_be();
+    pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
+        let ip = ((u32::from(a) << 24) |
+                  (u32::from(b) << 16) |
+                  (u32::from(c) <<  8) |
+                  (u32::from(d) <<  0)).to_be();
 
         Ipv4Addr(libc::in_addr { s_addr: ip })
     }
@@ -440,16 +424,16 @@
         Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
     }
 
-    pub const fn any() -> Ipv4Addr {
+    pub fn any() -> Ipv4Addr {
         Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
     }
 
-    pub const fn octets(self) -> [u8; 4] {
+    pub fn octets(self) -> [u8; 4] {
         let bits = u32::from_be(self.0.s_addr);
         [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
     }
 
-    pub const fn to_std(self) -> net::Ipv4Addr {
+    pub fn to_std(self) -> net::Ipv4Addr {
         let bits = self.octets();
         net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
     }
@@ -490,7 +474,7 @@
 impl Ipv6Addr {
     #[allow(clippy::many_single_char_names)]
     #[allow(clippy::too_many_arguments)]
-    pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
+    pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
         Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
     }
 
@@ -500,11 +484,11 @@
     }
 
     /// Return the eight 16-bit segments that make up this address
-    pub const fn segments(&self) -> [u16; 8] {
+    pub fn segments(&self) -> [u16; 8] {
         to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
     }
 
-    pub const fn to_std(&self) -> net::Ipv6Addr {
+    pub fn to_std(&self) -> net::Ipv6Addr {
         let s = self.segments();
         net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
     }
@@ -517,42 +501,15 @@
 }
 
 /// A wrapper around `sockaddr_un`.
+///
+/// This also tracks the length of `sun_path` address (excluding
+/// a terminating null), because it may not be null-terminated.  For example,
+/// unconnected and Linux abstract sockets are never null-terminated, and POSIX
+/// 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(Clone, Copy, Debug)]
-pub struct UnixAddr {
-    // INVARIANT: sun & path_len are valid as defined by docs for from_raw_parts
-    sun: libc::sockaddr_un,
-    path_len: usize,
-}
-
-// linux man page unix(7) says there are 3 kinds of unix socket:
-// pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
-// unnamed: addrlen = sizeof(sa_family_t)
-// abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))]
-//
-// what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path)
-#[derive(PartialEq, Eq, Hash)]
-enum UnixAddrKind<'a> {
-    Pathname(&'a Path),
-    Unnamed,
-    #[cfg(any(target_os = "android", target_os = "linux"))]
-    Abstract(&'a [u8]),
-}
-impl<'a> UnixAddrKind<'a> {
-    /// Safety: sun & path_len must be valid
-    unsafe fn get(sun: &'a libc::sockaddr_un, path_len: usize) -> Self {
-        if path_len == 0 {
-            return Self::Unnamed;
-        }
-        #[cfg(any(target_os = "android", target_os = "linux"))]
-        if sun.sun_path[0] == 0 {
-            let name =
-                slice::from_raw_parts(sun.sun_path.as_ptr().add(1) as *const u8, path_len - 1);
-            return Self::Abstract(name);
-        }
-        let pathname = slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len - 1);
-        Self::Pathname(Path::new(OsStr::from_bytes(pathname)))
-    }
-}
+pub struct UnixAddr(pub libc::sockaddr_un, pub usize);
 
 impl UnixAddr {
     /// Create a new sockaddr_un representing a filesystem path.
@@ -566,15 +523,15 @@
 
                 let bytes = cstr.to_bytes();
 
-                if bytes.len() >= ret.sun_path.len() {
-                    return Err(Errno::ENAMETOOLONG);
+                if bytes.len() > ret.sun_path.len() {
+                    return Err(Error::Sys(Errno::ENAMETOOLONG));
                 }
 
                 ptr::copy_nonoverlapping(bytes.as_ptr(),
                                          ret.sun_path.as_mut_ptr() as *mut u8,
                                          bytes.len());
 
-                Ok(UnixAddr::from_raw_parts(ret, bytes.len() + 1))
+                Ok(UnixAddr(ret, bytes.len()))
             }
         })?
     }
@@ -593,8 +550,8 @@
                 .. mem::zeroed()
             };
 
-            if path.len() >= ret.sun_path.len() {
-                return Err(Errno::ENAMETOOLONG);
+            if path.len() + 1 > ret.sun_path.len() {
+                return Err(Error::Sys(Errno::ENAMETOOLONG));
             }
 
             // Abstract addresses are represented by sun_path[0] ==
@@ -603,39 +560,28 @@
                                      ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
                                      path.len());
 
-            Ok(UnixAddr::from_raw_parts(ret, path.len() + 1))
+            Ok(UnixAddr(ret, path.len() + 1))
         }
     }
 
-    /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `path_len` is the "addrlen"
-    /// of this address, but minus `offsetof(struct sockaddr_un, sun_path)`. Basically the length
-    /// of the data in `sun_path`.
-    ///
-    /// # Safety
-    /// This pair of sockaddr_un & path_len must be a valid unix addr, which means:
-    /// - path_len <= sockaddr_un.sun_path.len()
-    /// - if this is a unix addr with a pathname, sun.sun_path is a nul-terminated fs path and
-    ///   sun.sun_path[path_len - 1] == 0 || sun.sun_path[path_len] == 0
-    pub(crate) unsafe fn from_raw_parts(sun: libc::sockaddr_un, mut path_len: usize) -> UnixAddr {
-        if let UnixAddrKind::Pathname(_) = UnixAddrKind::get(&sun, path_len) {
-            if sun.sun_path[path_len - 1] != 0 {
-                assert_eq!(sun.sun_path[path_len], 0);
-                path_len += 1
-            }
-        }
-        UnixAddr { sun, path_len }
-    }
-
-    fn kind(&self) -> UnixAddrKind<'_> {
-        // SAFETY: our sockaddr is always valid because of the invariant on the struct
-        unsafe { UnixAddrKind::get(&self.sun, self.path_len) }
+    fn sun_path(&self) -> &[u8] {
+        unsafe { slice::from_raw_parts(self.0.sun_path.as_ptr() as *const u8, self.1) }
     }
 
     /// If this address represents a filesystem path, return that path.
     pub fn path(&self) -> Option<&Path> {
-        match self.kind() {
-            UnixAddrKind::Pathname(path) => Some(path),
-            _ => None,
+        if self.1 == 0 || self.0.sun_path[0] == 0 {
+            // unnamed or abstract
+            None
+        } else {
+            let p = self.sun_path();
+            // POSIX only requires that `sun_len` be at least long enough to
+            // contain the pathname, and it need not be null-terminated.  So we
+            // need to create a string that is the shorter of the
+            // null-terminated length or the full length.
+            let ptr = &self.0.sun_path as *const libc::c_char;
+            let reallen = unsafe { libc::strnlen(ptr, p.len()) };
+            Some(Path::new(<OsStr as OsStrExt>::from_bytes(&p[..reallen])))
         }
     }
 
@@ -645,55 +591,31 @@
     /// leading null byte. `None` is returned for unnamed or path-backed sockets.
     #[cfg(any(target_os = "android", target_os = "linux"))]
     pub fn as_abstract(&self) -> Option<&[u8]> {
-        match self.kind() {
-            UnixAddrKind::Abstract(name) => Some(name),
-            _ => None,
+        if self.1 >= 1 && self.0.sun_path[0] == 0 {
+            Some(&self.sun_path()[1..])
+        } else {
+            // unnamed or filesystem path
+            None
         }
     }
-
-    /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)`
-    #[inline]
-    pub fn path_len(&self) -> usize {
-        self.path_len
-    }
-    /// Returns a pointer to the raw `sockaddr_un` struct
-    #[inline]
-    pub fn as_ptr(&self) -> *const libc::sockaddr_un {
-        &self.sun
-    }
-    /// Returns a mutable pointer to the raw `sockaddr_un` struct
-    #[inline]
-    pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un {
-        &mut self.sun
-    }
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
-    use fmt::Write;
-    f.write_str("@\"")?;
-    for &b in abs {
-        use fmt::Display;
-        char::from(b).escape_default().fmt(f)?;
-    }
-    f.write_char('"')?;
-    Ok(())
 }
 
 impl fmt::Display for UnixAddr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self.kind() {
-            UnixAddrKind::Pathname(path) => path.display().fmt(f),
-            UnixAddrKind::Unnamed => f.pad("<unbound UNIX socket>"),
-            #[cfg(any(target_os = "android", target_os = "linux"))]
-            UnixAddrKind::Abstract(name) => fmt_abstract(name, f),
+        if self.1 == 0 {
+            f.write_str("<unbound UNIX socket>")
+        } else if let Some(path) = self.path() {
+            path.display().fmt(f)
+        } else {
+            let display = String::from_utf8_lossy(&self.sun_path()[1..]);
+            write!(f, "@{}", display)
         }
     }
 }
 
 impl PartialEq for UnixAddr {
     fn eq(&self, other: &UnixAddr) -> bool {
-        self.kind() == other.kind()
+        self.sun_path() == other.sun_path()
     }
 }
 
@@ -701,13 +623,12 @@
 
 impl Hash for UnixAddr {
     fn hash<H: Hasher>(&self, s: &mut H) {
-        self.kind().hash(s)
+        ( self.0.sun_family, self.sun_path() ).hash(s)
     }
 }
 
 /// Represents a socket address
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[non_exhaustive]
 pub enum SockAddr {
     Inet(InetAddr),
     Unix(UnixAddr),
@@ -724,7 +645,6 @@
               target_os = "ios",
               target_os = "linux",
               target_os = "macos",
-              target_os = "illumos",
               target_os = "netbsd",
               target_os = "openbsd"))]
     Link(LinkAddr),
@@ -753,7 +673,7 @@
 
     #[cfg(any(target_os = "ios", target_os = "macos"))]
     pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
-        SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl)
+        SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
     }
 
     #[cfg(any(target_os = "android", target_os = "linux"))]
@@ -779,7 +699,6 @@
                       target_os = "ios",
                       target_os = "macos",
                       target_os = "netbsd",
-                      target_os = "illumos",
                       target_os = "openbsd"))]
             SockAddr::Link(..) => AddressFamily::Link,
             #[cfg(any(target_os = "android", target_os = "linux"))]
@@ -787,7 +706,6 @@
         }
     }
 
-    #[deprecated(since = "0.23.0", note = "use .to_string() instead")]
     pub fn to_str(&self) -> String {
         format!("{}", self)
     }
@@ -826,7 +744,6 @@
                           target_os = "ios",
                           target_os = "macos",
                           target_os = "netbsd",
-                          target_os = "illumos",
                           target_os = "openbsd"))]
                 Some(AddressFamily::Link) => {
                     let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
@@ -869,12 +786,12 @@
                 },
                 mem::size_of_val(addr) as libc::socklen_t
             ),
-            SockAddr::Unix(UnixAddr { ref sun, path_len }) => (
+            SockAddr::Unix(UnixAddr(ref addr, len)) => (
                 // This cast is always allowed in C
                 unsafe {
-                    &*(sun as *const libc::sockaddr_un as *const libc::sockaddr)
+                    &*(addr as *const libc::sockaddr_un as *const libc::sockaddr)
                 },
-                (path_len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t
+                (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t
             ),
             #[cfg(any(target_os = "android", target_os = "linux"))]
             SockAddr::Netlink(NetlinkAddr(ref sa)) => (
@@ -913,7 +830,6 @@
                       target_os = "freebsd",
                       target_os = "ios",
                       target_os = "macos",
-                      target_os = "illumos",
                       target_os = "netbsd",
                       target_os = "openbsd"))]
             SockAddr::Link(LinkAddr(ref addr)) => (
@@ -953,7 +869,6 @@
                       target_os = "linux",
                       target_os = "macos",
                       target_os = "netbsd",
-                      target_os = "illumos",
                       target_os = "openbsd"))]
             SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
             #[cfg(any(target_os = "android", target_os = "linux"))]
@@ -981,11 +896,11 @@
             NetlinkAddr(addr)
         }
 
-        pub const fn pid(&self) -> u32 {
+        pub fn pid(&self) -> u32 {
             self.0.nl_pid
         }
 
-        pub const fn groups(&self) -> u32 {
+        pub fn groups(&self) -> u32 {
             self.0.nl_groups
         }
     }
@@ -1066,7 +981,7 @@
     use libc::{self, c_uchar};
     use std::{fmt, mem};
     use std::os::unix::io::RawFd;
-    use crate::{Errno, Result};
+    use crate::{Errno, Error, Result};
 
     // FIXME: Move type into `libc`
     #[repr(C)]
@@ -1077,7 +992,7 @@
         pub ctl_name: [c_uchar; MAX_KCTL_NAME],
     }
 
-    const CTL_IOC_MAGIC: u8 = b'N';
+    const CTL_IOC_MAGIC: u8 = 'N' as u8;
     const CTL_IOC_INFO: u8 = 3;
     const MAX_KCTL_NAME: usize = 96;
 
@@ -1088,7 +1003,7 @@
     pub struct SysControlAddr(pub libc::sockaddr_ctl);
 
     impl SysControlAddr {
-        pub const fn new(id: u32, unit: u32) -> SysControlAddr {
+        pub fn new(id: u32, unit: u32) -> SysControlAddr {
             let addr = libc::sockaddr_ctl {
                 sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
                 sc_family: AddressFamily::System as c_uchar,
@@ -1103,7 +1018,7 @@
 
         pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
             if name.len() > MAX_KCTL_NAME {
-                return Err(Errno::ENAMETOOLONG);
+                return Err(Error::Sys(Errno::ENAMETOOLONG));
             }
 
             let mut ctl_name = [0; MAX_KCTL_NAME];
@@ -1115,11 +1030,11 @@
             Ok(SysControlAddr::new(info.ctl_id, unit))
         }
 
-        pub const fn id(&self) -> u32 {
+        pub fn id(&self) -> u32 {
             self.0.sc_id
         }
 
-        pub const fn unit(&self) -> u32 {
+        pub fn unit(&self) -> u32 {
             self.0.sc_unit
         }
     }
@@ -1203,7 +1118,6 @@
           target_os = "freebsd",
           target_os = "ios",
           target_os = "macos",
-          target_os = "illumos",
           target_os = "netbsd",
           target_os = "openbsd"))]
 mod datalink {
@@ -1215,7 +1129,6 @@
 
     impl LinkAddr {
         /// Total length of sockaddr
-        #[cfg(not(target_os = "illumos"))]
         pub fn len(&self) -> usize {
             self.0.sdl_len as usize
         }
@@ -1367,7 +1280,6 @@
               target_os = "linux",
               target_os = "macos",
               target_os = "netbsd",
-              target_os = "illumos",
               target_os = "openbsd"))]
     use super::*;
 
@@ -1412,36 +1324,17 @@
         };
     }
 
-    #[cfg(target_os = "illumos")]
-    #[test]
-    fn test_illumos_tap_datalink_addr() {
-        let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176];
-        let ptr = bytes.as_ptr();
-        let sa = ptr as *const libc::sockaddr;
-        let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
-
-        assert!(_sock_addr.is_some());
-
-        let sock_addr = _sock_addr.unwrap();
-
-        assert_eq!(sock_addr.family(), AddressFamily::Link);
-
-        match sock_addr {
-            SockAddr::Link(ether_addr) => {
-                assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
-            },
-            _ => { unreachable!() }
-        };
-    }
-
     #[cfg(any(target_os = "android", target_os = "linux"))]
     #[test]
     fn test_abstract_sun_path() {
         let name = String::from("nix\0abstract\0test");
         let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
 
-        let sun_path1 = unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] };
-        let sun_path2 = [0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
-        assert_eq!(sun_path1, sun_path2);
+        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];
+        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 97eea3d..11ed329 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -1,20 +1,16 @@
 //! Socket interface functions
 //!
-//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
+//! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
 use cfg_if::cfg_if;
-use crate::{Result, errno::Errno};
+use crate::{Error, Result, errno::Errno};
 use libc::{self, c_void, c_int, iovec, socklen_t, size_t,
         CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN};
-use memoffset::offset_of;
 use std::{mem, ptr, slice};
 use std::os::unix::io::RawFd;
-#[cfg(all(target_os = "linux"))]
-use crate::sys::time::TimeSpec;
 use crate::sys::time::TimeVal;
 use crate::sys::uio::IoVec;
 
 mod addr;
-#[deny(missing_docs)]
 pub mod sockopt;
 
 /*
@@ -23,7 +19,6 @@
  *
  */
 
-#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
 pub use self::addr::{
     AddressFamily,
     SockAddr,
@@ -34,17 +29,6 @@
     Ipv6Addr,
     LinkAddr,
 };
-#[cfg(any(target_os = "illumos", target_os = "solaris"))]
-pub use self::addr::{
-    AddressFamily,
-    SockAddr,
-    InetAddr,
-    UnixAddr,
-    IpAddr,
-    Ipv4Addr,
-    Ipv6Addr,
-};
-
 #[cfg(any(target_os = "android", target_os = "linux"))]
 pub use crate::sys::socket::addr::netlink::NetlinkAddr;
 #[cfg(any(target_os = "android", target_os = "linux"))]
@@ -71,7 +55,6 @@
 /// when creating a socket with [`socket()`](fn.socket.html)
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
 #[repr(i32)]
-#[non_exhaustive]
 pub enum SockType {
     /// Provides sequenced, reliable, two-way, connection-
     /// based byte streams.  An out-of-band data transmission
@@ -96,11 +79,10 @@
 /// to specify the protocol to use.
 #[repr(i32)]
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-#[non_exhaustive]
 pub enum SockProtocol {
-    /// TCP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
+    /// TCP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
     Tcp = libc::IPPROTO_TCP,
-    /// UDP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
+    /// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
     Udp = libc::IPPROTO_UDP,
     /// Allows applications and other KEXTs to be notified when certain kernel events occur
     /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
@@ -177,7 +159,6 @@
         #[cfg(any(target_os = "android",
                   target_os = "dragonfly",
                   target_os = "freebsd",
-                  target_os = "illumos",
                   target_os = "linux",
                   target_os = "netbsd",
                   target_os = "openbsd"))]
@@ -186,7 +167,6 @@
         #[cfg(any(target_os = "android",
                   target_os = "dragonfly",
                   target_os = "freebsd",
-                  target_os = "illumos",
                   target_os = "linux",
                   target_os = "netbsd",
                   target_os = "openbsd"))]
@@ -222,7 +202,7 @@
         /// (via the [`fcntl`](../../fcntl/fn.fcntl.html)
         /// `F_SETFL` operation), but differs in that `MSG_DONTWAIT` is a per-
         /// call option, whereas `O_NONBLOCK` is a setting on the open file
-        /// description (see [open(2)](https://man7.org/linux/man-pages/man2/open.2.html)),
+        /// description (see [open(2)](http://man7.org/linux/man-pages/man2/open.2.html)),
         /// which will affect all threads in
         /// the calling process and as well as other processes that hold
         /// file descriptors referring to the same open file description.
@@ -250,7 +230,7 @@
         /// file descriptor using the `SCM_RIGHTS` operation (described in
         /// [unix(7)](https://linux.die.net/man/7/unix)).
         /// This flag is useful for the same reasons as the `O_CLOEXEC` flag of
-        /// [open(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
+        /// [open(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
         ///
         /// Only used in [`recvmsg`](fn.recvmsg.html) function.
         #[cfg(any(target_os = "android",
@@ -311,9 +291,9 @@
             }
         }
 
-        impl From<UnixCredentials> for libc::ucred {
-            fn from(uc: UnixCredentials) -> Self {
-                uc.0
+        impl Into<libc::ucred> for UnixCredentials {
+            fn into(self) -> libc::ucred {
+                self.0
             }
         }
     } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
@@ -359,38 +339,6 @@
     }
 }
 
-cfg_if!{
-    if #[cfg(any(
-                target_os = "dragonfly",
-                target_os = "freebsd",
-                target_os = "macos",
-                target_os = "ios"
-        ))] {
-        /// Return type of [`LocalPeerCred`](crate::sys::socket::sockopt::LocalPeerCred)
-        #[repr(transparent)]
-        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-        pub struct XuCred(libc::xucred);
-
-        impl XuCred {
-            /// Structure layout version
-            pub fn version(&self) -> u32 {
-                self.0.cr_version
-            }
-
-            /// Effective user ID
-            pub fn uid(&self) -> libc::uid_t {
-                self.0.cr_uid
-            }
-
-            /// Returns a list of group identifiers (the first one being the
-            /// effective GID)
-            pub fn groups(&self) -> &[libc::gid_t] {
-                &self.0.cr_groups
-            }
-        }
-    }
-}
-
 /// Request for multicast socket operations
 ///
 /// This is a wrapper type around `ip_mreq`.
@@ -419,7 +367,7 @@
 
 impl Ipv6MembershipRequest {
     /// Instantiate a new `Ipv6MembershipRequest`
-    pub const fn new(group: Ipv6Addr) -> Self {
+    pub fn new(group: Ipv6Addr) -> Self {
         Ipv6MembershipRequest(libc::ipv6_mreq {
             ipv6mr_multiaddr: group.0,
             ipv6mr_interface: 0,
@@ -453,11 +401,13 @@
 macro_rules! cmsg_space {
     ( $( $x:ty ),* ) => {
         {
+            use nix::sys::socket::{c_uint, CMSG_SPACE};
+            use std::mem;
             let mut space = 0;
             $(
                 // CMSG_SPACE is always safe
                 space += unsafe {
-                    $crate::sys::socket::CMSG_SPACE(::std::mem::size_of::<$x>() as $crate::sys::socket::c_uint)
+                    CMSG_SPACE(mem::size_of::<$x>() as c_uint)
                 } as usize;
             )*
             Vec::<u8>::with_capacity(space)
@@ -517,7 +467,7 @@
 /// A type-safe wrapper around a single control message, as used with
 /// [`recvmsg`](#fn.recvmsg).
 ///
-/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
+/// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
 //  Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and
 //  sendmsg.  However, on some platforms the messages returned by recvmsg may be
 //  unaligned.  ControlMessageOwned takes those messages by copy, obviating any
@@ -525,14 +475,16 @@
 //
 //  See https://github.com/nix-rust/nix/issues/999
 #[derive(Clone, Debug, Eq, PartialEq)]
-#[non_exhaustive]
 pub enum ControlMessageOwned {
-    /// Received version of [`ControlMessage::ScmRights`]
+    /// Received version of
+    /// [`ControlMessage::ScmRights`][#enum.ControlMessage.html#variant.ScmRights]
     ScmRights(Vec<RawFd>),
-    /// Received version of [`ControlMessage::ScmCredentials`]
+    /// Received version of
+    /// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
     #[cfg(any(target_os = "android", target_os = "linux"))]
     ScmCredentials(UnixCredentials),
-    /// Received version of [`ControlMessage::ScmCreds`]
+    /// Received version of
+    /// [`ControlMessage::ScmCreds`][#enum.ControlMessage.html#variant.ScmCreds]
     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
     ScmCreds(UnixCredentials),
     /// A message of type `SCM_TIMESTAMP`, containing the time the
@@ -543,7 +495,6 @@
     ///
     /// # Examples
     ///
-    /// ```
     /// # #[macro_use] extern crate nix;
     /// # use nix::sys::socket::*;
     /// # use nix::sys::uio::IoVec;
@@ -591,11 +542,6 @@
     /// # }
     /// ```
     ScmTimestamp(TimeVal),
-    /// Nanoseconds resolution timestamp
-    ///
-    /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html)
-    #[cfg(all(target_os = "linux"))]
-    ScmTimestampns(TimeSpec),
     #[cfg(any(
         target_os = "android",
         target_os = "ios",
@@ -643,24 +589,6 @@
     #[cfg(target_os = "linux")]
     UdpGroSegments(u16),
 
-    /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
-    /// ancilliary msg (cmsg) should be attached to recieved
-    /// skbs indicating the number of packets dropped by the
-    /// socket between the last recieved packet and this
-    /// received packet.
-    ///
-    /// `RxqOvfl` socket option should be enabled on a socket
-    /// to allow receiving the drop counter.
-    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-    RxqOvfl(u32),
-
-    /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
-    #[cfg(any(target_os = "android", target_os = "linux"))]
-    Ipv4RecvErr(libc::sock_extended_err, Option<sockaddr_in>),
-    /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag.
-    #[cfg(any(target_os = "android", target_os = "linux"))]
-    Ipv6RecvErr(libc::sock_extended_err, Option<sockaddr_in6>),
-
     /// Catch-all variant for unimplemented cmsg types.
     #[doc(hidden)]
     Unknown(UnknownCmsg),
@@ -705,11 +633,6 @@
                 let tv: libc::timeval = ptr::read_unaligned(p as *const _);
                 ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
             },
-            #[cfg(all(target_os = "linux"))]
-            (libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => {
-                let ts: libc::timespec = ptr::read_unaligned(p as *const _);
-                ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts))
-            }
             #[cfg(any(
                 target_os = "android",
                 target_os = "freebsd",
@@ -759,61 +682,27 @@
                 let gso_size: u16 = ptr::read_unaligned(p as *const _);
                 ControlMessageOwned::UdpGroSegments(gso_size)
             },
-            #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-            (libc::SOL_SOCKET, libc::SO_RXQ_OVFL) => {
-                let drop_counter = ptr::read_unaligned(p as *const u32);
-                ControlMessageOwned::RxqOvfl(drop_counter)
-            },
-            #[cfg(any(target_os = "android", target_os = "linux"))]
-            (libc::IPPROTO_IP, libc::IP_RECVERR) => {
-                let (err, addr) = Self::recv_err_helper::<sockaddr_in>(p, len);
-                ControlMessageOwned::Ipv4RecvErr(err, addr)
-            },
-            #[cfg(any(target_os = "android", target_os = "linux"))]
-            (libc::IPPROTO_IPV6, libc::IPV6_RECVERR) => {
-                let (err, addr) = Self::recv_err_helper::<sockaddr_in6>(p, len);
-                ControlMessageOwned::Ipv6RecvErr(err, addr)
-            },
             (_, _) => {
                 let sl = slice::from_raw_parts(p, len);
-                let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(sl));
+                let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(&sl[..]));
                 ControlMessageOwned::Unknown(ucmsg)
             }
         }
     }
-
-    #[cfg(any(target_os = "android", target_os = "linux"))]
-    unsafe fn recv_err_helper<T>(p: *mut libc::c_uchar, len: usize) -> (libc::sock_extended_err, Option<T>) {
-        let ee = p as *const libc::sock_extended_err;
-        let err = ptr::read_unaligned(ee);
-
-        // For errors originating on the network, SO_EE_OFFENDER(ee) points inside the p[..len]
-        // CMSG_DATA buffer.  For local errors, there is no address included in the control
-        // message, and SO_EE_OFFENDER(ee) points beyond the end of the buffer.  So, we need to
-        // validate that the address object is in-bounds before we attempt to copy it.
-        let addrp = libc::SO_EE_OFFENDER(ee) as *const T;
-
-        if addrp.offset(1) as usize - (p as usize) > len {
-            (err, None)
-        } else {
-            (err, Some(ptr::read_unaligned(addrp)))
-        }
-    }
 }
 
 /// A type-safe zero-copy wrapper around a single control message, as used wih
 /// [`sendmsg`](#fn.sendmsg).  More types may be added to this enum; do not
 /// exhaustively pattern-match it.
 ///
-/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
+/// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-#[non_exhaustive]
 pub enum ControlMessage<'a> {
     /// A message of type `SCM_RIGHTS`, containing an array of file
     /// descriptors passed between processes.
     ///
     /// See the description in the "Ancillary messages" section of the
-    /// [unix(7) man page](https://man7.org/linux/man-pages/man7/unix.7.html).
+    /// [unix(7) man page](http://man7.org/linux/man-pages/man7/unix.7.html).
     ///
     /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
     /// recommended since it causes platform-dependent behaviour: It might
@@ -830,7 +719,7 @@
     /// processes are verified by the kernel.
     ///
     /// For further information, please refer to the
-    /// [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html) man page.
+    /// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page.
     #[cfg(any(target_os = "android", target_os = "linux"))]
     ScmCredentials(&'a UnixCredentials),
     /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
@@ -841,7 +730,7 @@
     ///
     /// Credentials are always overwritten by the kernel, so this variant does have
     /// any data, unlike the receive-side
-    /// [`ControlMessageOwned::ScmCreds`].
+    /// [`ControlMessageOwned::ScmCreds`][#enum.ControlMessageOwned.html#variant.ScmCreds].
     ///
     /// For further information, please refer to the
     /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
@@ -892,7 +781,7 @@
     /// Configure the sending addressing and interface for v4
     ///
     /// For further information, please refer to the
-    /// [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html) man page.
+    /// [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html) man page.
     #[cfg(any(target_os = "linux",
               target_os = "macos",
               target_os = "netbsd",
@@ -903,7 +792,7 @@
     /// Configure the sending addressing and interface for v6
     ///
     /// For further information, please refer to the
-    /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
+    /// [`ipv6(7)`](http://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
     #[cfg(any(target_os = "linux",
               target_os = "macos",
               target_os = "netbsd",
@@ -911,14 +800,6 @@
               target_os = "android",
               target_os = "ios",))]
     Ipv6PacketInfo(&'a libc::in6_pktinfo),
-
-    /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
-    /// ancilliary msg (cmsg) should be attached to recieved
-    /// skbs indicating the number of packets dropped by the
-    /// socket between the last recieved packet and this
-    /// received packet.
-    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-    RxqOvfl(&'a u32),
 }
 
 // An opaque structure used to prevent cmsghdr from being a public type
@@ -1009,10 +890,6 @@
                       target_os = "netbsd", target_os = "freebsd",
                       target_os = "android", target_os = "ios",))]
             ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
-            #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-            ControlMessage::RxqOvfl(drop_count) => {
-                drop_count as *const _ as *const u8
-            },
         };
         unsafe {
             ptr::copy_nonoverlapping(
@@ -1061,10 +938,6 @@
               target_os = "netbsd", target_os = "freebsd",
               target_os = "android", target_os = "ios",))]
             ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
-            #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-            ControlMessage::RxqOvfl(drop_count) => {
-                mem::size_of_val(drop_count)
-            },
         }
     }
 
@@ -1089,8 +962,6 @@
               target_os = "netbsd", target_os = "freebsd",
               target_os = "android", target_os = "ios",))]
             ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
-            #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-            ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET,
         }
     }
 
@@ -1126,10 +997,6 @@
                       target_os = "netbsd", target_os = "freebsd",
                       target_os = "android", target_os = "ios",))]
             ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
-            #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-            ControlMessage::RxqOvfl(_) => {
-                libc::SO_RXQ_OVFL
-            },
         }
     }
 
@@ -1222,22 +1089,23 @@
 
     let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);
 
-    let mut cmsgs_buffers = Vec::<Vec<u8>>::with_capacity(reserve_items);
+    let mut cmsgs_buffer = vec![0u8; 0];
 
     for d in iter {
-        let capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
-        let mut cmsgs_buffer = vec![0u8; capacity];
+        let cmsgs_start = cmsgs_buffer.len();
+        let cmsgs_required_capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
+        let cmsgs_buffer_need_capacity = cmsgs_start + cmsgs_required_capacity;
+        cmsgs_buffer.resize(cmsgs_buffer_need_capacity, 0);
 
         output.push(libc::mmsghdr {
             msg_hdr: pack_mhdr_to_send(
-                &mut cmsgs_buffer,
+                &mut cmsgs_buffer[cmsgs_start..],
                 &d.iov,
                 &d.cmsgs,
                 d.addr.as_ref()
             ),
             msg_len: 0,
         });
-        cmsgs_buffers.push(cmsgs_buffer);
     };
 
     let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) };
@@ -1300,7 +1168,6 @@
     target_os = "freebsd",
     target_os = "netbsd",
 ))]
-#[allow(clippy::needless_collect)]  // Complicated false positive
 pub fn recvmmsg<'a, I>(
     fd: RawFd,
     data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>,
@@ -1511,7 +1378,7 @@
 /// * `flags`:          Optional flags passed directly to the operating system.
 ///
 /// # References
-/// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
+/// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
 pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
                    mut cmsg_buffer: Option<&'a mut Vec<u8>>,
                    flags: MsgFlags) -> Result<RecvMsg<'a>>
@@ -1539,7 +1406,7 @@
 /// protocols may exist, in which case a particular protocol must be
 /// specified in this manner.
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
 pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
     let protocol = match protocol.into() {
         None => 0,
@@ -1559,7 +1426,7 @@
 
 /// Create a pair of connected sockets
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
 pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
                   flags: SockFlag) -> Result<(RawFd, RawFd)> {
     let protocol = match protocol.into() {
@@ -1583,7 +1450,7 @@
 
 /// Listen for connections on a socket
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
 pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
     let res = unsafe { libc::listen(sockfd, backlog as c_int) };
 
@@ -1592,7 +1459,7 @@
 
 /// Bind a name to a socket
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
 pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
     let res = unsafe {
         let (ptr, len) = addr.as_ffi_pair();
@@ -1604,7 +1471,7 @@
 
 /// Accept a connection on a socket
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
 pub fn accept(sockfd: RawFd) -> Result<RawFd> {
     let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
 
@@ -1613,15 +1480,8 @@
 
 /// Accept a connection on a socket
 ///
-/// [Further reading](https://man7.org/linux/man-pages/man2/accept.2.html)
-#[cfg(any(all(
-            target_os = "android",
-            any(
-                target_arch = "aarch64",
-                target_arch = "x86",
-                target_arch = "x86_64"
-            )
-          ),
+/// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
+#[cfg(any(target_os = "android",
           target_os = "freebsd",
           target_os = "linux",
           target_os = "openbsd"))]
@@ -1633,7 +1493,7 @@
 
 /// Initiate a connection on a socket
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
 pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
     let res = unsafe {
         let (ptr, len) = addr.as_ffi_pair();
@@ -1646,7 +1506,7 @@
 /// Receive data from a connection-oriented socket. Returns the number of
 /// bytes read
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
 pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
     unsafe {
         let ret = libc::recv(
@@ -1663,7 +1523,7 @@
 /// the number of bytes read and, for connectionless sockets,  the socket
 /// address of the sender.
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
 pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
     -> Result<(usize, Option<SockAddr>)>
 {
@@ -1680,7 +1540,7 @@
             &mut len as *mut socklen_t))? as usize;
 
         match sockaddr_storage_to_addr(&addr, len as usize) {
-            Err(Errno::ENOTCONN) => Ok((ret, None)),
+            Err(Error::Sys(Errno::ENOTCONN)) => Ok((ret, None)),
             Ok(addr) => Ok((ret, Some(addr))),
             Err(e) => Err(e)
         }
@@ -1689,7 +1549,7 @@
 
 /// Send a message to a socket
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
 pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
     let ret = unsafe {
         let (ptr, len) = addr.as_ffi_pair();
@@ -1701,7 +1561,7 @@
 
 /// Send data to a connection-oriented socket. Returns the number of bytes read
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
 pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
     let ret = unsafe {
         libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
@@ -1716,32 +1576,34 @@
  *
  */
 
-/// Represents a socket option that can be retrieved.
+/// Represents a socket option that can be accessed or set. Used as an argument
+/// to `getsockopt`
 pub trait GetSockOpt : Copy {
     type Val;
 
-    /// Look up the value of this socket option on the given socket.
+    #[doc(hidden)]
     fn get(&self, fd: RawFd) -> Result<Self::Val>;
 }
 
-/// Represents a socket option that can be set.
+/// Represents a socket option that can be accessed or set. Used as an argument
+/// to `setsockopt`
 pub trait SetSockOpt : Clone {
     type Val;
 
-    /// Set the value of this socket option on the given socket.
+    #[doc(hidden)]
     fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
 }
 
 /// Get the current value for the requested socket option
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
 pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
     opt.get(fd)
 }
 
 /// Sets the value for the requested socket option
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
 ///
 /// # Examples
 ///
@@ -1762,7 +1624,7 @@
 
 /// Get the address of the peer connected to the socket `fd`.
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
 pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
     unsafe {
         let mut addr = mem::MaybeUninit::uninit();
@@ -1782,7 +1644,7 @@
 
 /// Get the current address to which the socket `fd` is bound.
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
 pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
     unsafe {
         let mut addr = mem::MaybeUninit::uninit();
@@ -1812,21 +1674,21 @@
     addr: &sockaddr_storage,
     len: usize) -> Result<SockAddr> {
 
-    assert!(len <= mem::size_of::<sockaddr_storage>());
+    assert!(len <= mem::size_of::<sockaddr_un>());
     if len < mem::size_of_val(&addr.ss_family) {
-        return Err(Errno::ENOTCONN);
+        return Err(Error::Sys(Errno::ENOTCONN));
     }
 
     match c_int::from(addr.ss_family) {
         libc::AF_INET => {
-            assert!(len as usize >= mem::size_of::<sockaddr_in>());
+            assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
             let sin = unsafe {
                 *(addr as *const sockaddr_storage as *const sockaddr_in)
             };
             Ok(SockAddr::Inet(InetAddr::V4(sin)))
         }
         libc::AF_INET6 => {
-            assert!(len as usize >= mem::size_of::<sockaddr_in6>());
+            assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
             let sin6 = unsafe {
                 *(addr as *const _ as *const sockaddr_in6)
             };
@@ -1834,18 +1696,15 @@
         }
         libc::AF_UNIX => {
             let pathlen = len - offset_of!(sockaddr_un, sun_path);
-            unsafe {
-                let sun = *(addr as *const _ as *const sockaddr_un);
-                Ok(SockAddr::Unix(UnixAddr::from_raw_parts(sun, pathlen)))
-            }
+            let sun = unsafe {
+                *(addr as *const _ as *const sockaddr_un)
+            };
+            Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
         }
         #[cfg(any(target_os = "android", target_os = "linux"))]
         libc::AF_PACKET => {
             use libc::sockaddr_ll;
-            // Don't assert anything about the size.
-            // Apparently the Linux kernel can return smaller sizes when
-            // the value in the last element of sockaddr_ll (`sll_addr`) is
-            // smaller than the declared size of that field
+            assert_eq!(len as usize, mem::size_of::<sockaddr_ll>());
             let sll = unsafe {
                 *(addr as *const _ as *const sockaddr_ll)
             };
@@ -1892,7 +1751,7 @@
 
 /// Shut down part of a full-duplex connection.
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
 pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
     unsafe {
         use libc::shutdown;
@@ -1906,11 +1765,3 @@
         Errno::result(shutdown(df, how)).map(drop)
     }
 }
-
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn can_use_cmsg_space() {
-        let _ = cmsg_space!(u8);
-    }
-}
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs
index fcb4be8..5b7b4fe 100644
--- a/src/sys/socket/sockopt.rs
+++ b/src/sys/socket/sockopt.rs
@@ -1,4 +1,3 @@
-//! Socket options as used by `setsockopt` and `getsockopt`.
 use cfg_if::cfg_if;
 use super::{GetSockOpt, SetSockOpt};
 use crate::Result;
@@ -31,7 +30,7 @@
 /// # Arguments
 ///
 /// * `$name:ident`: name of the type you want to implement `SetSockOpt` for.
-/// * `$level:expr` : socket layer, or a `protocol level`: could be *raw sockets*
+/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets*
 ///    (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
 ///    and more. Please refer to your system manual for more options. Will be passed as the second
 ///    argument (`level`) to the `setsockopt` call.
@@ -42,7 +41,7 @@
 /// * Type that implements the `Set` trait for the type from the previous item (like `SetBool` for
 ///    `bool`, `SetUsize` for `usize`, etc.).
 macro_rules! setsockopt_impl {
-    ($name:ident, $level:expr, $flag:path, $ty:ty, $setter:ty) => {
+    ($name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
         impl SetSockOpt for $name {
             type Val = $ty;
 
@@ -83,7 +82,7 @@
 /// * Type that implements the `Get` trait for the type from the previous item (`GetBool` for
 ///    `bool`, `GetUsize` for `usize`, etc.).
 macro_rules! getsockopt_impl {
-    ($name:ident, $level:expr, $flag:path, $ty:ty, $getter:ty) => {
+    ($name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
         impl GetSockOpt for $name {
             type Val = $ty;
 
@@ -118,7 +117,7 @@
 /// * `GetOnly`, `SetOnly` or `Both`: whether you want to implement only getter, only setter or
 ///    both of them.
 /// * `$name:ident`: name of type `GetSockOpt`/`SetSockOpt` will be implemented for.
-/// * `$level:expr` : socket layer, or a `protocol level`: could be *raw sockets*
+/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets*
 ///    (`lic::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
 ///    and more. Please refer to your system manual for more options. Will be passed as the second
 ///    argument (`level`) to the `getsockopt`/`setsockopt` call.
@@ -129,99 +128,73 @@
 /// * `$getter:ty`: `Get` implementation; optional; only for `GetOnly` and `Both`.
 /// * `$setter:ty`: `Set` implementation; optional; only for `SetOnly` and `Both`.
 macro_rules! sockopt_impl {
-    ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, bool) => {
-        sockopt_impl!($(#[$attr])*
-                      $name, GetOnly, $level, $flag, bool, GetBool);
+    (GetOnly, $name:ident, $level:path, $flag:path, bool) => {
+        sockopt_impl!(GetOnly, $name, $level, $flag, bool, GetBool);
     };
 
-    ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, u8) => {
-        sockopt_impl!($(#[$attr])* $name, GetOnly, $level, $flag, u8, GetU8);
+    (GetOnly, $name:ident, $level:path, $flag:path, u8) => {
+        sockopt_impl!(GetOnly, $name, $level, $flag, u8, GetU8);
     };
 
-    ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, usize) =>
-    {
-        sockopt_impl!($(#[$attr])*
-                      $name, GetOnly, $level, $flag, usize, GetUsize);
+    (GetOnly, $name:ident, $level:path, $flag:path, usize) => {
+        sockopt_impl!(GetOnly, $name, $level, $flag, usize, GetUsize);
     };
 
-    ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, bool) => {
-        sockopt_impl!($(#[$attr])*
-                      $name, SetOnly, $level, $flag, bool, SetBool);
+    (SetOnly, $name:ident, $level:path, $flag:path, bool) => {
+        sockopt_impl!(SetOnly, $name, $level, $flag, bool, SetBool);
     };
 
-    ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, u8) => {
-        sockopt_impl!($(#[$attr])* $name, SetOnly, $level, $flag, u8, SetU8);
+    (SetOnly, $name:ident, $level:path, $flag:path, u8) => {
+        sockopt_impl!(SetOnly, $name, $level, $flag, u8, SetU8);
     };
 
-    ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, usize) =>
-    {
-        sockopt_impl!($(#[$attr])*
-                      $name, SetOnly, $level, $flag, usize, SetUsize);
+    (SetOnly, $name:ident, $level:path, $flag:path, usize) => {
+        sockopt_impl!(SetOnly, $name, $level, $flag, usize, SetUsize);
     };
 
-    ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, bool) => {
-        sockopt_impl!($(#[$attr])*
-                      $name, Both, $level, $flag, bool, GetBool, SetBool);
+    (Both, $name:ident, $level:path, $flag:path, bool) => {
+        sockopt_impl!(Both, $name, $level, $flag, bool, GetBool, SetBool);
     };
 
-    ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, u8) => {
-        sockopt_impl!($(#[$attr])*
-                      $name, Both, $level, $flag, u8, GetU8, SetU8);
+    (Both, $name:ident, $level:path, $flag:path, u8) => {
+        sockopt_impl!(Both, $name, $level, $flag, u8, GetU8, SetU8);
     };
 
-    ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, usize) => {
-        sockopt_impl!($(#[$attr])*
-                      $name, Both, $level, $flag, usize, GetUsize, SetUsize);
+    (Both, $name:ident, $level:path, $flag:path, usize) => {
+        sockopt_impl!(Both, $name, $level, $flag, usize, GetUsize, SetUsize);
     };
 
-    ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path,
-     OsString<$array:ty>) =>
-    {
-        sockopt_impl!($(#[$attr])*
-                      $name, Both, $level, $flag, OsString, GetOsString<$array>,
-                      SetOsString);
+    (Both, $name:ident, $level:path, $flag:path, OsString<$array:ty>) => {
+        sockopt_impl!(Both, $name, $level, $flag, OsString, GetOsString<$array>, SetOsString);
     };
 
     /*
      * Matchers with generic getter types must be placed at the end, so
      * they'll only match _after_ specialized matchers fail
      */
-    ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty) =>
-    {
-        sockopt_impl!($(#[$attr])*
-                      $name, GetOnly, $level, $flag, $ty, GetStruct<$ty>);
+    (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
+        sockopt_impl!(GetOnly, $name, $level, $flag, $ty, GetStruct<$ty>);
     };
 
-    ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty,
-     $getter:ty) =>
-    {
-        $(#[$attr])*
+    (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
         #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
         pub struct $name;
 
         getsockopt_impl!($name, $level, $flag, $ty, $getter);
     };
 
-    ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty) =>
-    {
-        sockopt_impl!($(#[$attr])*
-                      $name, SetOnly, $level, $flag, $ty, SetStruct<$ty>);
+    (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
+        sockopt_impl!(SetOnly, $name, $level, $flag, $ty, SetStruct<$ty>);
     };
 
-    ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty,
-     $setter:ty) =>
-    {
-        $(#[$attr])*
+    (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
         #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
         pub struct $name;
 
         setsockopt_impl!($name, $level, $flag, $ty, $setter);
     };
 
-    ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, $ty:ty,
-     $getter:ty, $setter:ty) =>
-    {
-        $(#[$attr])*
+    (Both, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty, $setter:ty) => {
         #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
         pub struct $name;
 
@@ -229,10 +202,8 @@
         getsockopt_impl!($name, $level, $flag, $ty, $getter);
     };
 
-    ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, $ty:ty) => {
-        sockopt_impl!($(#[$attr])*
-                      $name, Both, $level, $flag, $ty, GetStruct<$ty>,
-                      SetStruct<$ty>);
+    (Both, $name:ident, $level:path, $flag:path, $ty:ty) => {
+        sockopt_impl!(Both, $name, $level, $flag, $ty, GetStruct<$ty>, SetStruct<$ty>);
     };
 }
 
@@ -242,232 +213,74 @@
  *
  */
 
-sockopt_impl!(
-    /// Enables local address reuse
-    ReuseAddr, Both, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool
-);
-#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
-sockopt_impl!(
-    /// Permits multiple AF_INET or AF_INET6 sockets to be bound to an
-    /// identical socket address.
-    ReusePort, Both, libc::SOL_SOCKET, libc::SO_REUSEPORT, bool);
-sockopt_impl!(
-    /// Under most circumstances, TCP sends data when it is presented; when
-    /// outstanding data has not yet been acknowledged, it gathers small amounts
-    /// of output to be sent in a single packet once an acknowledgement is
-    /// received.  For a small number of clients, such as window systems that
-    /// send a stream of mouse events which receive no replies, this
-    /// packetization may cause significant delays.  The boolean option
-    /// TCP_NODELAY defeats this algorithm.
-    TcpNoDelay, Both, libc::IPPROTO_TCP, libc::TCP_NODELAY, bool);
-sockopt_impl!(
-    /// When enabled,  a close(2) or shutdown(2) will not return until all
-    /// queued messages for the socket have been successfully sent or the
-    /// linger timeout has been reached.
-    Linger, Both, libc::SOL_SOCKET, libc::SO_LINGER, libc::linger);
-sockopt_impl!(
-    /// Join a multicast group
-    IpAddMembership, SetOnly, libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP,
-    super::IpMembershipRequest);
-sockopt_impl!(
-    /// Leave a multicast group.
-    IpDropMembership, SetOnly, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP,
-    super::IpMembershipRequest);
+sockopt_impl!(Both, ReuseAddr, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool);
+sockopt_impl!(Both, ReusePort, libc::SOL_SOCKET, libc::SO_REUSEPORT, bool);
+sockopt_impl!(Both, TcpNoDelay, libc::IPPROTO_TCP, libc::TCP_NODELAY, bool);
+sockopt_impl!(Both, Linger, libc::SOL_SOCKET, libc::SO_LINGER, libc::linger);
+sockopt_impl!(SetOnly, IpAddMembership, libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP, super::IpMembershipRequest);
+sockopt_impl!(SetOnly, IpDropMembership, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, super::IpMembershipRequest);
 cfg_if! {
     if #[cfg(any(target_os = "android", target_os = "linux"))] {
-        sockopt_impl!(
-            /// Join an IPv6 multicast group.
-            Ipv6AddMembership, SetOnly, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::Ipv6MembershipRequest);
-        sockopt_impl!(
-            /// Leave an IPv6 multicast group.
-            Ipv6DropMembership, SetOnly, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest);
+        sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::Ipv6MembershipRequest);
+        sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest);
     } else if #[cfg(any(target_os = "dragonfly",
                         target_os = "freebsd",
-                        target_os = "illumos",
                         target_os = "ios",
                         target_os = "macos",
                         target_os = "netbsd",
-                        target_os = "openbsd",
-                        target_os = "solaris"))] {
-        sockopt_impl!(
-            /// Join an IPv6 multicast group.
-            Ipv6AddMembership, SetOnly, libc::IPPROTO_IPV6,
-            libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest);
-        sockopt_impl!(
-            /// Leave an IPv6 multicast group.
-            Ipv6DropMembership, SetOnly, libc::IPPROTO_IPV6,
-            libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest);
+                        target_os = "openbsd"))] {
+        sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest);
+        sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest);
     }
 }
-sockopt_impl!(
-    /// Set or read the time-to-live value of outgoing multicast packets for
-    /// this socket.
-    IpMulticastTtl, Both, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, u8);
-sockopt_impl!(
-    /// Set or read a boolean integer argument that determines whether sent
-    /// multicast packets should be looped back to the local sockets.
-    IpMulticastLoop, Both, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, bool);
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-sockopt_impl!(
-    /// If enabled, this boolean option allows binding to an IP address that
-    /// is nonlocal or does not (yet) exist.
-    IpFreebind, Both, libc::IPPROTO_IP, libc::IP_FREEBIND, bool);
-sockopt_impl!(
-    /// Specify the receiving timeout until reporting an error.
-    ReceiveTimeout, Both, libc::SOL_SOCKET, libc::SO_RCVTIMEO, TimeVal);
-sockopt_impl!(
-    /// Specify the sending timeout until reporting an error.
-    SendTimeout, Both, libc::SOL_SOCKET, libc::SO_SNDTIMEO, TimeVal);
-sockopt_impl!(
-    /// Set or get the broadcast flag.
-    Broadcast, Both, libc::SOL_SOCKET, libc::SO_BROADCAST, bool);
-sockopt_impl!(
-    /// If this option is enabled, out-of-band data is directly placed into
-    /// the receive data stream.
-    OobInline, Both, libc::SOL_SOCKET, libc::SO_OOBINLINE, bool);
-sockopt_impl!(
-    /// Get and clear the pending socket error.
-    SocketError, GetOnly, libc::SOL_SOCKET, libc::SO_ERROR, i32);
-sockopt_impl!(
-    /// Enable sending of keep-alive messages on connection-oriented sockets.
-    KeepAlive, Both, libc::SOL_SOCKET, libc::SO_KEEPALIVE, bool);
-#[cfg(any(
-        target_os = "dragonfly",
-        target_os = "freebsd",
-        target_os = "macos",
-        target_os = "ios"
-))]
-sockopt_impl!(
-    /// Get the credentials of the peer process of a connected unix domain
-    /// socket.
-    LocalPeerCred, GetOnly, 0, libc::LOCAL_PEERCRED, super::XuCred);
+sockopt_impl!(Both, IpMulticastTtl, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, u8);
+sockopt_impl!(Both, IpMulticastLoop, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, bool);
+sockopt_impl!(Both, ReceiveTimeout, libc::SOL_SOCKET, libc::SO_RCVTIMEO, TimeVal);
+sockopt_impl!(Both, SendTimeout, libc::SOL_SOCKET, libc::SO_SNDTIMEO, TimeVal);
+sockopt_impl!(Both, Broadcast, libc::SOL_SOCKET, libc::SO_BROADCAST, bool);
+sockopt_impl!(Both, OobInline, libc::SOL_SOCKET, libc::SO_OOBINLINE, bool);
+sockopt_impl!(GetOnly, SocketError, libc::SOL_SOCKET, libc::SO_ERROR, i32);
+sockopt_impl!(Both, KeepAlive, libc::SOL_SOCKET, libc::SO_KEEPALIVE, bool);
 #[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    /// Return the credentials of the foreign process connected to this socket.
-    PeerCredentials, GetOnly, libc::SOL_SOCKET, libc::SO_PEERCRED, super::UnixCredentials);
+sockopt_impl!(GetOnly, PeerCredentials, libc::SOL_SOCKET, libc::SO_PEERCRED, super::UnixCredentials);
 #[cfg(any(target_os = "ios",
           target_os = "macos"))]
-sockopt_impl!(
-    /// Specify the amount of time, in seconds, that the connection must be idle
-    /// before keepalive probes (if enabled) are sent.
-    TcpKeepAlive, Both, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32);
+sockopt_impl!(Both, TcpKeepAlive, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32);
 #[cfg(any(target_os = "android",
           target_os = "dragonfly",
           target_os = "freebsd",
           target_os = "linux",
           target_os = "nacl"))]
-sockopt_impl!(
-    /// The time (in seconds) the connection needs to remain idle before TCP
-    /// starts sending keepalive probes
-    TcpKeepIdle, Both, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32);
-cfg_if! {
-    if #[cfg(any(target_os = "android", target_os = "linux"))] {
-        sockopt_impl!(
-            /// The maximum segment size for outgoing TCP packets.
-            TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
-    } else {
-        sockopt_impl!(
-            /// The maximum segment size for outgoing TCP packets.
-            TcpMaxSeg, GetOnly, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);
-    }
-}
+sockopt_impl!(Both, TcpKeepIdle, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32);
 #[cfg(not(target_os = "openbsd"))]
-sockopt_impl!(
-    /// The maximum number of keepalive probes TCP should send before
-    /// dropping the connection.
-    TcpKeepCount, Both, libc::IPPROTO_TCP, libc::TCP_KEEPCNT, u32);
-#[cfg(any(target_os = "android",
-          target_os = "fuchsia",
-          target_os = "linux"))]
-sockopt_impl!(
-    #[allow(missing_docs)]
-    // Not documented by Linux!
-    TcpRepair, Both, libc::IPPROTO_TCP, libc::TCP_REPAIR, u32);
+sockopt_impl!(Both, TcpKeepCount, libc::IPPROTO_TCP, libc::TCP_KEEPCNT, u32);
 #[cfg(not(target_os = "openbsd"))]
-sockopt_impl!(
-    /// The time (in seconds) between individual keepalive probes.
-    TcpKeepInterval, Both, libc::IPPROTO_TCP, libc::TCP_KEEPINTVL, u32);
-#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
-sockopt_impl!(
-    /// Specifies the maximum amount of time in milliseconds that transmitted
-    /// data may remain unacknowledged before TCP will forcibly close the
-    /// corresponding connection
-    TcpUserTimeout, Both, libc::IPPROTO_TCP, libc::TCP_USER_TIMEOUT, u32);
-sockopt_impl!(
-    /// Sets or gets the maximum socket receive buffer in bytes.
-    RcvBuf, Both, libc::SOL_SOCKET, libc::SO_RCVBUF, usize);
-sockopt_impl!(
-    /// Sets or gets the maximum socket send buffer in bytes.
-    SndBuf, Both, libc::SOL_SOCKET, libc::SO_SNDBUF, usize);
+sockopt_impl!(Both, TcpKeepInterval, libc::IPPROTO_TCP, libc::TCP_KEEPINTVL, u32);
+sockopt_impl!(Both, RcvBuf, libc::SOL_SOCKET, libc::SO_RCVBUF, usize);
+sockopt_impl!(Both, SndBuf, libc::SOL_SOCKET, libc::SO_SNDBUF, usize);
 #[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    /// Using this socket option, a privileged (`CAP_NET_ADMIN`) process can
-    /// perform the same task as `SO_RCVBUF`, but the `rmem_max limit` can be
-    /// overridden.
-    RcvBufForce, SetOnly, libc::SOL_SOCKET, libc::SO_RCVBUFFORCE, usize);
+sockopt_impl!(SetOnly, RcvBufForce, libc::SOL_SOCKET, libc::SO_RCVBUFFORCE, usize);
 #[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    /// Using this socket option, a privileged (`CAP_NET_ADMIN`)  process can
-    /// perform the same task as `SO_SNDBUF`, but the `wmem_max` limit can be
-    /// overridden.
-    SndBufForce, SetOnly, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usize);
-sockopt_impl!(
-    /// Gets the socket type as an integer.
-    SockType, GetOnly, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType);
-sockopt_impl!(
-    /// Returns a value indicating whether or not this socket has been marked to
-    /// accept connections with `listen(2)`.
-    AcceptConn, GetOnly, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
+sockopt_impl!(SetOnly, SndBufForce, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usize);
+sockopt_impl!(GetOnly, SockType, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType);
+sockopt_impl!(GetOnly, AcceptConn, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
 #[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    /// Bind this socket to a particular device like “eth0”.
-    BindToDevice, Both, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]>);
+sockopt_impl!(Both, BindToDevice, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]>);
 #[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    #[allow(missing_docs)]
-    // Not documented by Linux!
-    OriginalDst, GetOnly, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in);
+sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in);
+sockopt_impl!(Both, ReceiveTimestamp, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
 #[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    #[allow(missing_docs)]
-    // Not documented by Linux!
-    Ip6tOriginalDst, GetOnly, libc::SOL_IPV6, libc::IP6T_SO_ORIGINAL_DST, libc::sockaddr_in6);
-sockopt_impl!( 
-    /// Enable or disable the receiving of the `SO_TIMESTAMP` control message.
-    ReceiveTimestamp, Both, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
-#[cfg(all(target_os = "linux"))]
-sockopt_impl!(
-    /// Enable or disable the receiving of the `SO_TIMESTAMPNS` control message.
-    ReceiveTimestampns, Both, libc::SOL_SOCKET, libc::SO_TIMESTAMPNS, bool);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    /// Setting this boolean option enables transparent proxying on this socket.
-    IpTransparent, Both, libc::SOL_IP, libc::IP_TRANSPARENT, bool);
+sockopt_impl!(Both, IpTransparent, libc::SOL_IP, libc::IP_TRANSPARENT, bool);
 #[cfg(target_os = "openbsd")]
-sockopt_impl!(
-    /// Allows the socket to be bound to addresses which are not local to the
-    /// machine, so it can be used to make a transparent proxy.
-    BindAny, Both, libc::SOL_SOCKET, libc::SO_BINDANY, bool);
+sockopt_impl!(Both, BindAny, libc::SOL_SOCKET, libc::SO_BINDANY, bool);
 #[cfg(target_os = "freebsd")]
-sockopt_impl!(
-    /// Can `bind(2)` to any address, even one not bound to any available
-    /// network interface in the system.
-    BindAny, Both, libc::IPPROTO_IP, libc::IP_BINDANY, bool);
+sockopt_impl!(Both, BindAny, libc::IPPROTO_IP, libc::IP_BINDANY, bool);
 #[cfg(target_os = "linux")]
-sockopt_impl!(
-    /// Set the mark for each packet sent through this socket (similar to the
-    /// netfilter MARK target but socket-based).
-    Mark, Both, libc::SOL_SOCKET, libc::SO_MARK, u32);
+sockopt_impl!(Both, Mark, libc::SOL_SOCKET, libc::SO_MARK, u32);
 #[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    /// Enable or disable the receiving of the `SCM_CREDENTIALS` control
-    /// message.
-    PassCred, Both, libc::SOL_SOCKET, libc::SO_PASSCRED, bool);
+sockopt_impl!(Both, PassCred, libc::SOL_SOCKET, libc::SO_PASSCRED, bool);
 #[cfg(any(target_os = "freebsd", target_os = "linux"))] 
-sockopt_impl!(
-    /// This option allows the caller to set the TCP congestion control
-    /// algorithm to be used,  on a per-socket basis.
-    TcpCongestion, Both, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>);
+sockopt_impl!(Both, TcpCongestion, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>);
 #[cfg(any(
     target_os = "android",
     target_os = "ios",
@@ -475,10 +288,7 @@
     target_os = "macos",
     target_os = "netbsd",
 ))]
-sockopt_impl!(
-    /// Pass an `IP_PKTINFO` ancillary message that contains a pktinfo
-    /// structure that supplies some information about the incoming packet.
-    Ipv4PacketInfo, Both, libc::IPPROTO_IP, libc::IP_PKTINFO, bool);
+sockopt_impl!(Both, Ipv4PacketInfo, libc::IPPROTO_IP, libc::IP_PKTINFO, bool);
 #[cfg(any(
     target_os = "android",
     target_os = "freebsd",
@@ -488,10 +298,7 @@
     target_os = "netbsd",
     target_os = "openbsd",
 ))]
-sockopt_impl!(
-    /// Set delivery of the `IPV6_PKTINFO` control message on incoming
-    /// datagrams.
-    Ipv6RecvPacketInfo, Both, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool);
+sockopt_impl!(Both, Ipv6RecvPacketInfo, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool);
 #[cfg(any(
     target_os = "freebsd",
     target_os = "ios",
@@ -499,10 +306,7 @@
     target_os = "netbsd",
     target_os = "openbsd",
 ))]
-sockopt_impl!(
-    /// The `recvmsg(2)` call returns a `struct sockaddr_dl` corresponding to
-    /// the interface on which the packet was received.
-    Ipv4RecvIf, Both, libc::IPPROTO_IP, libc::IP_RECVIF, bool);
+sockopt_impl!(Both, Ipv4RecvIf, libc::IPPROTO_IP, libc::IP_RECVIF, bool);
 #[cfg(any(
     target_os = "freebsd",
     target_os = "ios",
@@ -510,49 +314,12 @@
     target_os = "netbsd",
     target_os = "openbsd",
 ))]
-sockopt_impl!(
-    /// The `recvmsg(2)` call will return the destination IP address for a UDP
-    /// datagram.
-    Ipv4RecvDstAddr, Both, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool);
+sockopt_impl!(Both, Ipv4RecvDstAddr, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool);
 #[cfg(target_os = "linux")]
-sockopt_impl!(
-    #[allow(missing_docs)]
-    // Not documented by Linux!
-    UdpGsoSegment, Both, libc::SOL_UDP, libc::UDP_SEGMENT, libc::c_int);
+sockopt_impl!(Both, UdpGsoSegment, libc::SOL_UDP, libc::UDP_SEGMENT, libc::c_int);
 #[cfg(target_os = "linux")]
-sockopt_impl!(
-    #[allow(missing_docs)]
-    // Not documented by Linux!
-    UdpGroSegment, Both, libc::IPPROTO_UDP, libc::UDP_GRO, bool);
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-sockopt_impl!(
-    /// Indicates that an unsigned 32-bit value ancillary message (cmsg) should
-    /// be attached to received skbs indicating the number of packets dropped by
-    /// the socket since its creation.
-    RxqOvfl, Both, libc::SOL_SOCKET, libc::SO_RXQ_OVFL, libc::c_int);
-sockopt_impl!(
-    /// The socket is restricted to sending and receiving IPv6 packets only.
-    Ipv6V6Only, Both, libc::IPPROTO_IPV6, libc::IPV6_V6ONLY, bool);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    /// Enable extended reliable error message passing.
-    Ipv4RecvErr, Both, libc::IPPROTO_IP, libc::IP_RECVERR, bool);
-#[cfg(any(target_os = "android", target_os = "linux"))]
-sockopt_impl!(
-    /// Control receiving of asynchronous error options.
-    Ipv6RecvErr, Both, libc::IPPROTO_IPV6, libc::IPV6_RECVERR, bool);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
-sockopt_impl!(
-    /// Set or retrieve the current time-to-live field that is used in every
-    /// packet sent from this socket.
-    Ipv4Ttl, Both, libc::IPPROTO_IP, libc::IP_TTL, libc::c_int);
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
-sockopt_impl!(
-    /// Set the unicast hop limit for the socket.
-    Ipv6Ttl, Both, libc::IPPROTO_IPV6, libc::IPV6_UNICAST_HOPS, libc::c_int);
+sockopt_impl!(Both, UdpGroSegment, libc::IPPROTO_UDP, libc::UDP_GRO, bool);
 
-#[allow(missing_docs)]
-// Not documented by Linux!
 #[cfg(any(target_os = "android", target_os = "linux"))]
 #[derive(Copy, Clone, Debug)]
 pub struct AlgSetAeadAuthSize;
@@ -575,8 +342,6 @@
     }
 }
 
-#[allow(missing_docs)]
-// Not documented by Linux!
 #[cfg(any(target_os = "android", target_os = "linux"))]
 #[derive(Clone, Debug)]
 pub struct AlgSetKey<T>(::std::marker::PhantomData<T>);
@@ -611,9 +376,9 @@
  */
 
 /// Helper trait that describes what is expected from a `GetSockOpt` getter.
-trait Get<T> {
+unsafe trait Get<T> {
     /// Returns an uninitialized value.
-    fn uninit() -> Self;
+    unsafe fn uninit() -> Self;
     /// Returns a pointer to the stored value. This pointer will be passed to the system's
     /// `getsockopt` call (`man 3p getsockopt`, argument `option_value`).
     fn ffi_ptr(&mut self) -> *mut c_void;
@@ -625,7 +390,7 @@
 }
 
 /// Helper trait that describes what is expected from a `SetSockOpt` setter.
-trait Set<'a, T> {
+unsafe trait Set<'a, T> {
     /// Initialize the setter with a given value.
     fn new(val: &'a T) -> Self;
     /// Returns a pointer to the stored value. This pointer will be passed to the system's
@@ -642,8 +407,8 @@
     val: MaybeUninit<T>,
 }
 
-impl<T> Get<T> for GetStruct<T> {
-    fn uninit() -> Self {
+unsafe impl<T> Get<T> for GetStruct<T> {
+    unsafe fn uninit() -> Self {
         GetStruct {
             len: mem::size_of::<T>() as socklen_t,
             val: MaybeUninit::uninit(),
@@ -669,7 +434,7 @@
     ptr: &'a T,
 }
 
-impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
+unsafe impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
     fn new(ptr: &'a T) -> SetStruct<'a, T> {
         SetStruct { ptr }
     }
@@ -689,8 +454,8 @@
     val: MaybeUninit<c_int>,
 }
 
-impl Get<bool> for GetBool {
-    fn uninit() -> Self {
+unsafe impl Get<bool> for GetBool {
+    unsafe fn uninit() -> Self {
         GetBool {
             len: mem::size_of::<c_int>() as socklen_t,
             val: MaybeUninit::uninit(),
@@ -716,7 +481,7 @@
     val: c_int,
 }
 
-impl<'a> Set<'a, bool> for SetBool {
+unsafe impl<'a> Set<'a, bool> for SetBool {
     fn new(val: &'a bool) -> SetBool {
         SetBool { val: if *val { 1 } else { 0 } }
     }
@@ -736,8 +501,8 @@
     val: MaybeUninit<u8>,
 }
 
-impl Get<u8> for GetU8 {
-    fn uninit() -> Self {
+unsafe impl Get<u8> for GetU8 {
+    unsafe fn uninit() -> Self {
         GetU8 {
             len: mem::size_of::<u8>() as socklen_t,
             val: MaybeUninit::uninit(),
@@ -763,7 +528,7 @@
     val: u8,
 }
 
-impl<'a> Set<'a, u8> for SetU8 {
+unsafe impl<'a> Set<'a, u8> for SetU8 {
     fn new(val: &'a u8) -> SetU8 {
         SetU8 { val: *val as u8 }
     }
@@ -783,8 +548,8 @@
     val: MaybeUninit<c_int>,
 }
 
-impl Get<usize> for GetUsize {
-    fn uninit() -> Self {
+unsafe impl Get<usize> for GetUsize {
+    unsafe fn uninit() -> Self {
         GetUsize {
             len: mem::size_of::<c_int>() as socklen_t,
             val: MaybeUninit::uninit(),
@@ -810,7 +575,7 @@
     val: c_int,
 }
 
-impl<'a> Set<'a, usize> for SetUsize {
+unsafe impl<'a> Set<'a, usize> for SetUsize {
     fn new(val: &'a usize) -> SetUsize {
         SetUsize { val: *val as c_int }
     }
@@ -830,8 +595,8 @@
     val: MaybeUninit<T>,
 }
 
-impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
-    fn uninit() -> Self {
+unsafe impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
+    unsafe fn uninit() -> Self {
         GetOsString {
             len: mem::size_of::<T>() as socklen_t,
             val: MaybeUninit::uninit(),
@@ -858,7 +623,7 @@
     val: &'a OsStr,
 }
 
-impl<'a> Set<'a, OsString> for SetOsString<'a> {
+unsafe impl<'a> Set<'a, OsString> for SetOsString<'a> {
     fn new(val: &'a OsString) -> SetOsString {
         SetOsString { val: val.as_os_str() }
     }
diff --git a/src/sys/stat.rs b/src/sys/stat.rs
index c8f1041..df81a2c 100644
--- a/src/sys/stat.rs
+++ b/src/sys/stat.rs
@@ -9,7 +9,6 @@
 use crate::sys::time::{TimeSpec, TimeVal};
 
 libc_bitflags!(
-    /// "File type" flags for `mknod` and related functions.
     pub struct SFlag: mode_t {
         S_IFIFO;
         S_IFCHR;
@@ -23,7 +22,6 @@
 );
 
 libc_bitflags! {
-    /// "File mode / permissions" flags.
     pub struct Mode: mode_t {
         S_IRWXU;
         S_IRUSR;
@@ -43,45 +41,30 @@
     }
 }
 
-/// Create a special or ordinary file, by pathname.
 pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
-    let res = path.with_nix_path(|cstr| unsafe {
-        libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
-    })?;
-
-    Errno::result(res).map(drop)
-}
-
-/// Create a special or ordinary file, relative to a given directory.
-#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
-pub fn mknodat<P: ?Sized + NixPath>(
-    dirfd: RawFd,
-    path: &P,
-    kind: SFlag,
-    perm: Mode,
-    dev: dev_t,
-) -> Result<()> {
-    let res = path.with_nix_path(|cstr| unsafe {
-        libc::mknodat(dirfd, cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
+    let res = path.with_nix_path(|cstr| {
+        unsafe {
+            libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
+        }
     })?;
 
     Errno::result(res).map(drop)
 }
 
 #[cfg(target_os = "linux")]
-pub const fn major(dev: dev_t) -> u64 {
+pub fn major(dev: dev_t) -> u64 {
     ((dev >> 32) & 0xffff_f000) |
     ((dev >>  8) & 0x0000_0fff)
 }
 
 #[cfg(target_os = "linux")]
-pub const fn minor(dev: dev_t) -> u64 {
+pub fn minor(dev: dev_t) -> u64 {
     ((dev >> 12) & 0xffff_ff00) |
     ((dev      ) & 0x0000_00ff)
 }
 
 #[cfg(target_os = "linux")]
-pub const fn makedev(major: u64, minor: u64) -> dev_t {
+pub fn makedev(major: u64, minor: u64) -> dev_t {
     ((major & 0xffff_f000) << 32) |
     ((major & 0x0000_0fff) <<  8) |
     ((minor & 0xffff_ff00) << 12) |
@@ -144,7 +127,7 @@
 ///
 /// # References
 ///
-/// [fchmod(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
+/// [fchmod(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
 pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> {
     let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) };
 
@@ -173,7 +156,7 @@
 ///
 /// # References
 ///
-/// [fchmodat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
+/// [fchmodat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
 #[cfg(not(target_os = "redox"))]
 pub fn fchmodat<P: ?Sized + NixPath>(
     dirfd: Option<RawFd>,
@@ -207,7 +190,7 @@
 ///
 /// # References
 ///
-/// [utimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
+/// [utimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
 pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
     let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
     let res = path.with_nix_path(|cstr| unsafe {
@@ -226,7 +209,7 @@
 ///
 /// # References
 ///
-/// [lutimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
+/// [lutimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
 #[cfg(any(target_os = "linux",
           target_os = "haiku",
           target_os = "ios",
@@ -246,7 +229,7 @@
 ///
 /// # References
 ///
-/// [futimens(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
+/// [futimens(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
 #[inline]
 pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> {
     let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
@@ -256,7 +239,6 @@
 }
 
 /// Flags for `utimensat` function.
-// TODO: replace with fcntl::AtFlags
 #[derive(Clone, Copy, Debug)]
 pub enum UtimensatFlags {
     FollowSymlink,
@@ -278,7 +260,7 @@
 ///
 /// # References
 ///
-/// [utimensat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
+/// [utimensat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
 #[cfg(not(target_os = "redox"))]
 pub fn utimensat<P: ?Sized + NixPath>(
     dirfd: Option<RawFd>,
diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs
index 829be57..27b7259 100644
--- a/src/sys/statfs.rs
+++ b/src/sys/statfs.rs
@@ -1,6 +1,3 @@
-//! Get filesystem statistics, non-portably
-//!
-//! See [`statvfs`](crate::sys::statvfs) for a portable alternative.
 use std::fmt::{self, Debug};
 use std::mem;
 use std::os::unix::io::AsRawFd;
@@ -9,14 +6,11 @@
 
 use crate::{NixPath, Result, errno::Errno};
 
-/// Identifies a mounted file system
 #[cfg(target_os = "android")]
 pub type fsid_t = libc::__fsid_t;
-/// Identifies a mounted file system
 #[cfg(not(target_os = "android"))]
 pub type fsid_t = libc::fsid_t;
 
-/// Describes a mounted file system
 #[derive(Clone, Copy)]
 #[repr(transparent)]
 pub struct Statfs(libc::statfs);
@@ -32,7 +26,6 @@
 #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
 type fs_type_t = libc::__fsword_t;
 
-/// Describes the file system type as known by the operating system.
 #[cfg(any(
     target_os = "freebsd",
     target_os = "android",
@@ -43,94 +36,63 @@
 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
 pub struct FsType(pub fs_type_t);
 
-// These constants are defined without documentation in the Linux headers, so we
-// can't very well document them here.
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
 #[cfg(all(target_os = "linux", not(target_env = "musl")))]
-#[allow(missing_docs)]
 pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
 
 
@@ -489,14 +451,6 @@
     }
 }
 
-/// Describes a mounted file system.
-///
-/// The result is OS-dependent.  For a portabable alternative, see
-/// [`statvfs`](crate::sys::statvfs::statvfs).
-///
-/// # Arguments
-///
-/// `path` - Path to any file within the file system to describe
 pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
     unsafe {
         let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
@@ -505,14 +459,6 @@
     }
 }
 
-/// Describes a mounted file system.
-///
-/// The result is OS-dependent.  For a portabable alternative, see
-/// [`fstatvfs`](crate::sys::statvfs::fstatvfs).
-///
-/// # Arguments
-///
-/// `fd` - File descriptor of any open file within the file system to describe
 pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
     unsafe {
         let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs
index 15e7a7d..9bea973 100644
--- a/src/sys/statvfs.rs
+++ b/src/sys/statvfs.rs
@@ -1,6 +1,6 @@
 //! Get filesystem statistics
 //!
-//! See [the man pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
+//! See [the man pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
 //! for more details.
 use std::mem;
 use std::os::unix::io::AsRawFd;
@@ -54,7 +54,7 @@
 
 /// Wrapper around the POSIX `statvfs` struct
 ///
-/// For more information see the [`statvfs(3)` man pages](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
+/// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
 #[repr(transparent)]
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub struct Statvfs(libc::statvfs);
@@ -150,7 +150,7 @@
 
     #[test]
     fn statvfs_call() {
-        statvfs(&b"/"[..]).unwrap();
+        statvfs("/".as_bytes()).unwrap();
     }
 
     #[test]
diff --git a/src/sys/sysinfo.rs b/src/sys/sysinfo.rs
index dc943c1..222a2fc 100644
--- a/src/sys/sysinfo.rs
+++ b/src/sys/sysinfo.rs
@@ -71,7 +71,7 @@
 
 /// Returns system information.
 ///
-/// [See `sysinfo(2)`](https://man7.org/linux/man-pages/man2/sysinfo.2.html).
+/// [See `sysinfo(2)`](http://man7.org/linux/man-pages/man2/sysinfo.2.html).
 pub fn sysinfo() -> Result<SysInfo> {
     let mut info = mem::MaybeUninit::uninit();
     let res = unsafe { libc::sysinfo(info.as_mut_ptr()) };
diff --git a/src/sys/termios.rs b/src/sys/termios.rs
index 01d4608..c30de80 100644
--- a/src/sys/termios.rs
+++ b/src/sys/termios.rs
@@ -5,7 +5,7 @@
 //! types here or exported directly.
 //!
 //! If you are unfamiliar with the `termios` API, you should first read the
-//! [API documentation](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html) and
+//! [API documentation](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html) and
 //! then come back to understand how `nix` safely wraps it.
 //!
 //! It should be noted that this API incurs some runtime overhead above the base `libc` definitions.
@@ -152,11 +152,11 @@
 //! # }
 //! ```
 use cfg_if::cfg_if;
-use crate::Result;
+use crate::{Error, Result};
 use crate::errno::Errno;
 use libc::{self, c_int, tcflag_t};
 use std::cell::{Ref, RefCell};
-use std::convert::From;
+use std::convert::{From, TryFrom};
 use std::mem;
 use std::os::unix::io::RawFd;
 
@@ -256,7 +256,6 @@
     /// B0 is special and will disable the port.
     #[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))]
     #[cfg_attr(not(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64")), repr(u32))]
-    #[non_exhaustive]
     pub enum BaudRate {
         B0,
         B50,
@@ -300,17 +299,11 @@
                 target_os = "openbsd"))]
         B76800,
         B115200,
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-        B153600,
         B230400,
-        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-        B307200,
         #[cfg(any(target_os = "android",
                   target_os = "freebsd",
-                  target_os = "illumos",
                   target_os = "linux",
-                  target_os = "netbsd",
-                  target_os = "solaris"))]
+                  target_os = "netbsd"))]
         B460800,
         #[cfg(any(target_os = "android", target_os = "linux"))]
         B500000,
@@ -318,10 +311,8 @@
         B576000,
         #[cfg(any(target_os = "android",
                   target_os = "freebsd",
-                  target_os = "illumos",
                   target_os = "linux",
-                  target_os = "netbsd",
-                  target_os = "solaris"))]
+                  target_os = "netbsd"))]
         B921600,
         #[cfg(any(target_os = "android", target_os = "linux"))]
         B1000000,
@@ -340,7 +331,107 @@
         #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
         B4000000,
     }
-    impl TryFrom<libc::speed_t>
+}
+
+impl TryFrom<libc::speed_t> for BaudRate {
+    type Error = Error;
+
+    fn try_from(s: libc::speed_t) -> Result<BaudRate> {
+        use libc::{B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800,
+                   B9600, B19200, B38400, B57600, B115200, B230400};
+        #[cfg(any(target_os = "android", target_os = "linux"))]
+        use libc::{B500000, B576000, B1000000, B1152000, B1500000, B2000000};
+        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
+        use libc::{B2500000, B3000000, B3500000, B4000000};
+        #[cfg(any(target_os = "dragonfly",
+                  target_os = "freebsd",
+                  target_os = "macos",
+                  target_os = "netbsd",
+                  target_os = "openbsd"))]
+        use libc::{B7200, B14400, B28800, B76800};
+        #[cfg(any(target_os = "android",
+                  target_os = "freebsd",
+                  target_os = "linux",
+                  target_os = "netbsd"))]
+        use libc::{B460800, B921600};
+
+        match s {
+            B0 => Ok(BaudRate::B0),
+            B50 => Ok(BaudRate::B50),
+            B75 => Ok(BaudRate::B75),
+            B110 => Ok(BaudRate::B110),
+            B134 => Ok(BaudRate::B134),
+            B150 => Ok(BaudRate::B150),
+            B200 => Ok(BaudRate::B200),
+            B300 => Ok(BaudRate::B300),
+            B600 => Ok(BaudRate::B600),
+            B1200 => Ok(BaudRate::B1200),
+            B1800 => Ok(BaudRate::B1800),
+            B2400 => Ok(BaudRate::B2400),
+            B4800 => Ok(BaudRate::B4800),
+            #[cfg(any(target_os = "dragonfly",
+                      target_os = "freebsd",
+                      target_os = "macos",
+                      target_os = "netbsd",
+                      target_os = "openbsd"))]
+            B7200 => Ok(BaudRate::B7200),
+            B9600 => Ok(BaudRate::B9600),
+            #[cfg(any(target_os = "dragonfly",
+                      target_os = "freebsd",
+                      target_os = "macos",
+                      target_os = "netbsd",
+                      target_os = "openbsd"))]
+            B14400 => Ok(BaudRate::B14400),
+            B19200 => Ok(BaudRate::B19200),
+            #[cfg(any(target_os = "dragonfly",
+                      target_os = "freebsd",
+                      target_os = "macos",
+                      target_os = "netbsd",
+                      target_os = "openbsd"))]
+            B28800 => Ok(BaudRate::B28800),
+            B38400 => Ok(BaudRate::B38400),
+            B57600 => Ok(BaudRate::B57600),
+            #[cfg(any(target_os = "dragonfly",
+                      target_os = "freebsd",
+                      target_os = "macos",
+                      target_os = "netbsd",
+                      target_os = "openbsd"))]
+            B76800 => Ok(BaudRate::B76800),
+            B115200 => Ok(BaudRate::B115200),
+            B230400 => Ok(BaudRate::B230400),
+            #[cfg(any(target_os = "android",
+                      target_os = "freebsd",
+                      target_os = "linux",
+                      target_os = "netbsd"))]
+            B460800 => Ok(BaudRate::B460800),
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            B500000 => Ok(BaudRate::B500000),
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            B576000 => Ok(BaudRate::B576000),
+            #[cfg(any(target_os = "android",
+                      target_os = "freebsd",
+                      target_os = "linux",
+                      target_os = "netbsd"))]
+            B921600 => Ok(BaudRate::B921600),
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            B1000000 => Ok(BaudRate::B1000000),
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            B1152000 => Ok(BaudRate::B1152000),
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            B1500000 => Ok(BaudRate::B1500000),
+            #[cfg(any(target_os = "android", target_os = "linux"))]
+            B2000000 => Ok(BaudRate::B2000000),
+            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
+            B2500000 => Ok(BaudRate::B2500000),
+            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
+            B3000000 => Ok(BaudRate::B3000000),
+            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
+            B3500000 => Ok(BaudRate::B3500000),
+            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
+            B4000000 => Ok(BaudRate::B4000000),
+            _ => Err(Error::invalid_argument())
+        }
+    }
 }
 
 #[cfg(any(target_os = "freebsd",
@@ -361,7 +452,6 @@
     ///
     /// Used as an argument to `tcsetattr()`
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum SetArg {
         /// The change will occur immediately
         TCSANOW,
@@ -377,7 +467,6 @@
     ///
     /// Used as an argument to `tcflush()`.
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum FlushArg {
         /// Flush data that was received but not read
         TCIFLUSH,
@@ -393,7 +482,6 @@
     ///
     /// Used as an argument to `tcflow()`.
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum FlowArg {
         /// Suspend transmission
         TCOOFF,
@@ -410,51 +498,41 @@
 libc_enum! {
     /// Indices into the `termios.c_cc` array for special characters.
     #[repr(usize)]
-    #[non_exhaustive]
     pub enum SpecialCharacterIndices {
         VDISCARD,
         #[cfg(any(target_os = "dragonfly",
                 target_os = "freebsd",
-                target_os = "illumos",
                 target_os = "macos",
                 target_os = "netbsd",
-                target_os = "openbsd",
-                target_os = "solaris"))]
+                target_os = "openbsd"))]
         VDSUSP,
         VEOF,
         VEOL,
         VEOL2,
         VERASE,
-        #[cfg(any(target_os = "dragonfly",
-                  target_os = "freebsd",
-                  target_os = "illumos",
-                  target_os = "solaris"))]
+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
         VERASE2,
         VINTR,
         VKILL,
         VLNEXT,
-        #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
-                target_os = "illumos", target_os = "solaris")))]
+        #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
         VMIN,
         VQUIT,
         VREPRINT,
         VSTART,
         #[cfg(any(target_os = "dragonfly",
                 target_os = "freebsd",
-                target_os = "illumos",
                 target_os = "macos",
                 target_os = "netbsd",
-                target_os = "openbsd",
-                target_os = "solaris"))]
+                target_os = "openbsd"))]
         VSTATUS,
         VSTOP,
         VSUSP,
         #[cfg(target_os = "linux")]
         VSWTC,
-        #[cfg(any(target_os = "haiku", target_os = "illumos", target_os = "solaris"))]
+        #[cfg(target_os = "haiku")]
         VSWTCH,
-        #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
-                target_os = "illumos", target_os = "solaris")))]
+        #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
         VTIME,
         VWERASE,
         #[cfg(target_os = "dragonfly")]
@@ -462,8 +540,7 @@
     }
 }
 
-#[cfg(any(all(target_os = "linux", target_arch = "sparc64"),
-        target_os = "illumos", target_os = "solaris"))]
+#[cfg(all(target_os = "linux", target_arch = "sparc64"))]
 impl SpecialCharacterIndices {
     pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF;
     pub const VTIME: SpecialCharacterIndices = SpecialCharacterIndices::VEOL;
@@ -492,9 +569,7 @@
         ICRNL;
         IXON;
         IXOFF;
-        #[cfg(not(target_os = "redox"))]
         IXANY;
-        #[cfg(not(target_os = "redox"))]
         IMAXBEL;
         #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
         IUTF8;
@@ -801,7 +876,7 @@
                  target_os = "netbsd",
                  target_os = "openbsd"))] {
         /// Get input baud rate (see
-        /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
+        /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
         ///
         /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
         pub fn cfgetispeed(termios: &Termios) -> u32 {
@@ -810,7 +885,7 @@
         }
 
         /// Get output baud rate (see
-        /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
+        /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
         ///
         /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
         pub fn cfgetospeed(termios: &Termios) -> u32 {
@@ -819,7 +894,7 @@
         }
 
         /// Set input baud rate (see
-        /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
+        /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
         ///
         /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
         pub fn cfsetispeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
@@ -830,7 +905,7 @@
         }
 
         /// Set output baud rate (see
-        /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
+        /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
         ///
         /// `cfsetospeed()` sets the output baud rate in the given termios structure.
         pub fn cfsetospeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
@@ -855,7 +930,7 @@
         use std::convert::TryInto;
 
         /// Get input baud rate (see
-        /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
+        /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
         ///
         /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
         pub fn cfgetispeed(termios: &Termios) -> BaudRate {
@@ -864,7 +939,7 @@
         }
 
         /// Get output baud rate (see
-        /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
+        /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
         ///
         /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
         pub fn cfgetospeed(termios: &Termios) -> BaudRate {
@@ -873,7 +948,7 @@
         }
 
         /// Set input baud rate (see
-        /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
+        /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
         ///
         /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
         pub fn cfsetispeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
@@ -884,7 +959,7 @@
         }
 
         /// Set output baud rate (see
-        /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
+        /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
         ///
         /// `cfsetospeed()` sets the output baud rate in the given `Termios` structure.
         pub fn cfsetospeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
@@ -909,7 +984,7 @@
 }
 
 /// Configures the port to something like the "raw" mode of the old Version 7 terminal driver (see
-/// [termios(3)](https://man7.org/linux/man-pages/man3/termios.3.html)).
+/// [termios(3)](http://man7.org/linux/man-pages/man3/termios.3.html)).
 ///
 /// `cfmakeraw()` configures the termios structure such that input is available character-by-
 /// character, echoing is disabled, and all special input and output processing is disabled. Note
@@ -936,7 +1011,7 @@
 }
 
 /// Return the configuration of a port
-/// [tcgetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)).
+/// [tcgetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)).
 ///
 /// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying
 /// this structure *will not* reconfigure the port, instead the modifications should be done to
@@ -952,7 +1027,7 @@
 }
 
 /// Set the configuration for a terminal (see
-/// [tcsetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)).
+/// [tcsetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)).
 ///
 /// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change
 /// takes affect at a time specified by `actions`. Note that this function may return success if
@@ -963,13 +1038,13 @@
 }
 
 /// Block until all output data is written (see
-/// [tcdrain(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
+/// [tcdrain(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
 pub fn tcdrain(fd: RawFd) -> Result<()> {
     Errno::result(unsafe { libc::tcdrain(fd) }).map(drop)
 }
 
 /// Suspend or resume the transmission or reception of data (see
-/// [tcflow(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)).
+/// [tcflow(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)).
 ///
 /// `tcflow()` suspends of resumes the transmission or reception of data for the given port
 /// depending on the value of `action`.
@@ -978,7 +1053,7 @@
 }
 
 /// Discard data in the output or input queue (see
-/// [tcflush(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)).
+/// [tcflush(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)).
 ///
 /// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both
 /// depending on the value of `action`.
@@ -987,7 +1062,7 @@
 }
 
 /// Send a break for a specific duration (see
-/// [tcsendbreak(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)).
+/// [tcsendbreak(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)).
 ///
 /// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream
 /// of zero-valued bits for an implementation-defined duration.
@@ -996,7 +1071,7 @@
 }
 
 /// Get the session controlled by the given terminal (see
-/// [tcgetsid(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
+/// [tcgetsid(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
 pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
     let res = unsafe { libc::tcgetsid(fd) };
 
@@ -1006,7 +1081,6 @@
 #[cfg(test)]
 mod test {
     use super::*;
-    use std::convert::TryFrom;
 
     #[test]
     fn try_from() {
diff --git a/src/sys/time.rs b/src/sys/time.rs
index ac42471..7546d1b 100644
--- a/src/sys/time.rs
+++ b/src/sys/time.rs
@@ -77,7 +77,11 @@
 
 impl From<Duration> for TimeSpec {
     fn from(duration: Duration) -> Self {
-        Self::from_duration(duration)
+        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
+        TimeSpec(timespec {
+            tv_sec: duration.as_secs() as time_t,
+            tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t
+        })
     }
 }
 
@@ -187,25 +191,13 @@
     }
 
     #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-    pub const fn tv_sec(&self) -> time_t {
+    pub fn tv_sec(&self) -> time_t {
         self.0.tv_sec
     }
 
-    pub const fn tv_nsec(&self) -> timespec_tv_nsec_t {
+    pub fn tv_nsec(&self) -> timespec_tv_nsec_t {
         self.0.tv_nsec
     }
-
-    pub const fn from_duration(duration: Duration) -> Self {
-        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-        TimeSpec(timespec {
-            tv_sec: duration.as_secs() as time_t,
-            tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t
-        })
-    }
-
-    pub const fn from_timespec(timespec: timespec) -> Self {
-        Self(timespec)
-    }
 }
 
 impl ops::Neg for TimeSpec {
@@ -404,11 +396,11 @@
     }
 
     #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-    pub const fn tv_sec(&self) -> time_t {
+    pub fn tv_sec(&self) -> time_t {
         self.0.tv_sec
     }
 
-    pub const fn tv_usec(&self) -> suseconds_t {
+    pub fn tv_usec(&self) -> suseconds_t {
         self.0.tv_usec
     }
 }
diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs
index 705a3c4..4a24719 100644
--- a/src/sys/timerfd.rs
+++ b/src/sys/timerfd.rs
@@ -3,7 +3,7 @@
 //! Timer FD is a Linux-only API to create timers and get expiration
 //! notifications through file descriptors.
 //!
-//! For more documentation, please read [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html).
+//! For more documentation, please read [timerfd_create(2)](http://man7.org/linux/man-pages/man2/timerfd_create.2.html).
 //!
 //! # Examples
 //!
@@ -30,7 +30,7 @@
 //! ```
 use crate::sys::time::TimeSpec;
 use crate::unistd::read;
-use crate::{errno::Errno, Result};
+use crate::{errno::Errno, Error, Result};
 use bitflags::bitflags;
 use libc::c_int;
 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
@@ -56,9 +56,8 @@
 
 libc_enum! {
     /// The type of the clock used to mark the progress of the timer. For more
-    /// details on each kind of clock, please refer to [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html).
+    /// details on each kind of clock, please refer to [timerfd_create(2)](http://man7.org/linux/man-pages/man2/timerfd_create.2.html).
     #[repr(i32)]
-    #[non_exhaustive]
     pub enum ClockId {
         CLOCK_REALTIME,
         CLOCK_MONOTONIC,
@@ -88,7 +87,7 @@
 struct TimerSpec(libc::itimerspec);
 
 impl TimerSpec {
-    pub const fn none() -> Self {
+    pub fn none() -> Self {
         Self(libc::itimerspec {
             it_interval: libc::timespec {
                 tv_sec: 0,
@@ -257,9 +256,14 @@
     ///
     /// Note: If the alarm is unset, then you will wait forever.
     pub fn wait(&self) -> Result<()> {
-        while let Err(e) = read(self.fd, &mut [0u8; 8]) {
-            if e != Errno::EINTR {
-                return Err(e)
+        loop {
+            if let Err(e) = read(self.fd, &mut [0u8; 8]) {
+                match e {
+                    Error::Sys(Errno::EINTR) => continue,
+                    _ => return Err(e),
+                }
+            } else {
+                break;
             }
         }
 
@@ -273,7 +277,7 @@
             let result = Errno::result(unsafe {
                 libc::close(self.fd)
             });
-            if let Err(Errno::EBADF) = result {
+            if let Err(Error::Sys(Errno::EBADF)) = result {
                 panic!("close of TimerFd encountered EBADF");
             }
         }
diff --git a/src/sys/uio.rs b/src/sys/uio.rs
index 3abcde2..6533422 100644
--- a/src/sys/uio.rs
+++ b/src/sys/uio.rs
@@ -1,4 +1,5 @@
-//! Vectored I/O
+// Silence invalid warnings due to rust-lang/rust#16719
+#![allow(improper_ctypes)]
 
 use crate::Result;
 use crate::errno::Errno;
@@ -6,18 +7,12 @@
 use std::marker::PhantomData;
 use std::os::unix::io::RawFd;
 
-/// Low-level vectored write to a raw file descriptor
-///
-/// See also [writev(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html)
 pub fn writev(fd: RawFd, iov: &[IoVec<&[u8]>]) -> Result<usize> {
     let res = unsafe { libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
 
     Errno::result(res).map(|r| r as usize)
 }
 
-/// Low-level vectored read from a raw file descriptor
-///
-/// See also [readv(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html)
 pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
     let res = unsafe { libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
 
@@ -30,7 +25,11 @@
 /// or an error occurs. The file offset is not changed.
 ///
 /// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
-#[cfg(not(target_os = "redox"))]
+#[cfg(any(target_os = "dragonfly",
+          target_os = "freebsd",
+          target_os = "linux",
+          target_os = "netbsd",
+          target_os = "openbsd"))]
 pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
                offset: off_t) -> Result<usize> {
     let res = unsafe {
@@ -47,7 +46,11 @@
 /// changed.
 ///
 /// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
-#[cfg(not(target_os = "redox"))]
+#[cfg(any(target_os = "dragonfly",
+          target_os = "freebsd",
+          target_os = "linux",
+          target_os = "netbsd",
+          target_os = "openbsd"))]
 pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>],
               offset: off_t) -> Result<usize> {
     let res = unsafe {
@@ -57,10 +60,6 @@
     Errno::result(res).map(|r| r as usize)
 }
 
-/// Low-level write to a file, with specified offset.
-///
-/// See also [pwrite(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html)
-// TODO: move to unistd
 pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
     let res = unsafe {
         libc::pwrite(fd, buf.as_ptr() as *const c_void, buf.len() as size_t,
@@ -70,10 +69,6 @@
     Errno::result(res).map(|r| r as usize)
 }
 
-/// Low-level write to a file, with specified offset.
-///
-/// See also [pread(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html)
-// TODO: move to unistd
 pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{
     let res = unsafe {
         libc::pread(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t,
@@ -117,7 +112,7 @@
 ///
 /// This function is only available on Linux.
 ///
-/// [`process_vm_writev`(2)]: https://man7.org/linux/man-pages/man2/process_vm_writev.2.html
+/// [`process_vm_writev`(2)]: http://man7.org/linux/man-pages/man2/process_vm_writev.2.html
 /// [ptrace]: ../ptrace/index.html
 /// [`IoVec`]: struct.IoVec.html
 /// [`RemoteIoVec`]: struct.RemoteIoVec.html
@@ -152,7 +147,7 @@
 ///
 /// This function is only available on Linux.
 ///
-/// [`process_vm_readv`(2)]: https://man7.org/linux/man-pages/man2/process_vm_readv.2.html
+/// [`process_vm_readv`(2)]: http://man7.org/linux/man-pages/man2/process_vm_readv.2.html
 /// [`ptrace`]: ../ptrace/index.html
 /// [`IoVec`]: struct.IoVec.html
 /// [`RemoteIoVec`]: struct.RemoteIoVec.html
@@ -171,17 +166,11 @@
     Errno::result(res).map(|r| r as usize)
 }
 
-/// A vector of buffers.
-///
-/// Vectored I/O methods like [`writev`] and [`readv`] use this structure for
-/// both reading and writing.  Each `IoVec` specifies the base address and
-/// length of an area in memory.
 #[repr(transparent)]
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-pub struct IoVec<T>(pub(crate) libc::iovec, PhantomData<T>);
+pub struct IoVec<T>(libc::iovec, PhantomData<T>);
 
 impl<T> IoVec<T> {
-    /// View the `IoVec` as a Rust slice.
     #[inline]
     pub fn as_slice(&self) -> &[u8] {
         use std::slice;
@@ -195,15 +184,6 @@
 }
 
 impl<'a> IoVec<&'a [u8]> {
-    #[cfg(target_os = "freebsd")]
-    pub(crate) fn from_raw_parts(base: *mut c_void, len: usize) -> Self {
-        IoVec(libc::iovec {
-            iov_base: base,
-            iov_len: len
-        }, PhantomData)
-    }
-
-    /// Create an `IoVec` from a Rust slice.
     pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> {
         IoVec(libc::iovec {
             iov_base: buf.as_ptr() as *mut c_void,
@@ -213,7 +193,6 @@
 }
 
 impl<'a> IoVec<&'a mut [u8]> {
-    /// Create an `IoVec` from a mutable Rust slice.
     pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> {
         IoVec(libc::iovec {
             iov_base: buf.as_ptr() as *mut c_void,
diff --git a/src/sys/utsname.rs b/src/sys/utsname.rs
index 98edee0..bf1a814 100644
--- a/src/sys/utsname.rs
+++ b/src/sys/utsname.rs
@@ -1,42 +1,34 @@
-//! Get system identification
 use std::mem;
 use libc::{self, c_char};
 use std::ffi::CStr;
 use std::str::from_utf8_unchecked;
 
-/// Describes the running system.  Return type of [`uname`].
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 #[repr(transparent)]
 pub struct UtsName(libc::utsname);
 
 impl UtsName {
-    /// Name of the operating system implementation
     pub fn sysname(&self) -> &str {
         to_str(&(&self.0.sysname as *const c_char ) as *const *const c_char)
     }
 
-    /// Network name of this machine.
     pub fn nodename(&self) -> &str {
         to_str(&(&self.0.nodename as *const c_char ) as *const *const c_char)
     }
 
-    /// Release level of the operating system.
     pub fn release(&self) -> &str {
         to_str(&(&self.0.release as *const c_char ) as *const *const c_char)
     }
 
-    /// Version level of the operating system.
     pub fn version(&self) -> &str {
         to_str(&(&self.0.version as *const c_char ) as *const *const c_char)
     }
 
-    /// Machine hardware platform.
     pub fn machine(&self) -> &str {
         to_str(&(&self.0.machine as *const c_char ) as *const *const c_char)
     }
 }
 
-/// Get system identification
 pub fn uname() -> UtsName {
     unsafe {
         let mut ret = mem::MaybeUninit::uninit();
diff --git a/src/sys/wait.rs b/src/sys/wait.rs
index ee49e37..faf8543 100644
--- a/src/sys/wait.rs
+++ b/src/sys/wait.rs
@@ -1,4 +1,3 @@
-//! Wait for a process to change status
 use crate::errno::Errno;
 use crate::sys::signal::Signal;
 use crate::unistd::Pid;
@@ -8,17 +7,9 @@
 use std::convert::TryFrom;
 
 libc_bitflags!(
-    /// Controls the behavior of [`waitpid`].
     pub struct WaitPidFlag: c_int {
-        /// Do not block when there are no processes wishing to report status.
         WNOHANG;
-        /// Report the status of selected processes which are stopped due to a
-        /// [`SIGTTIN`](crate::sys::signal::Signal::SIGTTIN),
-        /// [`SIGTTOU`](crate::sys::signal::Signal::SIGTTOU),
-        /// [`SIGTSTP`](crate::sys::signal::Signal::SIGTSTP), or
-        /// [`SIGSTOP`](crate::sys::signal::Signal::SIGSTOP) signal.
         WUNTRACED;
-        /// Report the status of selected processes which have terminated.
         #[cfg(any(target_os = "android",
                   target_os = "freebsd",
                   target_os = "haiku",
@@ -28,11 +19,7 @@
                   target_os = "macos",
                   target_os = "netbsd"))]
         WEXITED;
-        /// Report the status of selected processes that have continued from a
-        /// job control stop by receiving a
-        /// [`SIGCONT`](crate::sys::signal::Signal::SIGCONT) signal.
         WCONTINUED;
-        /// An alias for WUNTRACED.
         #[cfg(any(target_os = "android",
                   target_os = "freebsd",
                   target_os = "haiku",
@@ -58,7 +45,6 @@
         /// Wait on all children, regardless of type
         #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
         __WALL;
-        /// Wait for "clone" children only.
         #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
         __WCLONE;
     }
@@ -95,14 +81,14 @@
     /// field is the `PTRACE_EVENT_*` value of the event.
     ///
     /// [`nix::sys::ptrace`]: ../ptrace/index.html
-    /// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html
+    /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
     #[cfg(any(target_os = "linux", target_os = "android"))]
     PtraceEvent(Pid, Signal, c_int),
     /// The traced process was stopped by execution of a system call,
     /// and `PTRACE_O_TRACESYSGOOD` is in effect. See [`ptrace`(2)] for
     /// more information.
     ///
-    /// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html
+    /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
     #[cfg(any(target_os = "linux", target_os = "android"))]
     PtraceSyscall(Pid),
     /// The process was previously stopped but has resumed execution
@@ -227,9 +213,6 @@
     }
 }
 
-/// Wait for a process to change status
-///
-/// See also [waitpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html)
 pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
     use self::WaitStatus::*;
 
@@ -254,9 +237,6 @@
     }
 }
 
-/// Wait for any child process to change status or a signal is received.
-///
-/// See also [wait(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html)
 pub fn wait() -> Result<WaitStatus> {
     waitpid(None, None)
 }
diff --git a/src/time.rs b/src/time.rs
index 6275b59..e6c3f8d 100644
--- a/src/time.rs
+++ b/src/time.rs
@@ -6,7 +6,7 @@
     target_os = "android",
     target_os = "emscripten",
 ))]
-use crate::unistd::Pid;
+use crate::{unistd::Pid, Error};
 use crate::{Errno, Result};
 use libc::{self, clockid_t};
 use std::mem::MaybeUninit;
@@ -20,7 +20,7 @@
 
 impl ClockId {
     /// Creates `ClockId` from raw `clockid_t`
-    pub const fn from_raw(clk_id: clockid_t) -> Self {
+    pub fn from_raw(clk_id: clockid_t) -> Self {
         ClockId(clk_id)
     }
 
@@ -61,7 +61,7 @@
     }
 
     /// Gets the raw `clockid_t` wrapped by `self`
-    pub const fn as_raw(self) -> clockid_t {
+    pub fn as_raw(self) -> clockid_t {
         self.0
     }
 
@@ -185,9 +185,9 @@
     pub const CLOCK_VIRTUAL: ClockId = ClockId(libc::CLOCK_VIRTUAL);
 }
 
-impl From<ClockId> for clockid_t {
-    fn from(clock_id: ClockId) -> Self {
-        clock_id.as_raw()
+impl Into<clockid_t> for ClockId {
+    fn into(self) -> clockid_t {
+        self.as_raw()
     }
 }
 
@@ -255,6 +255,6 @@
         let res = unsafe { clk_id.assume_init() };
         Ok(ClockId::from(res))
     } else {
-        Err(Errno::from_i32(ret))
+        Err(Error::Sys(Errno::from_i32(ret)))
     }
 }
diff --git a/src/ucontext.rs b/src/ucontext.rs
index f2338bd..a5b8cc7 100644
--- a/src/ucontext.rs
+++ b/src/ucontext.rs
@@ -1,3 +1,4 @@
+use libc;
 #[cfg(not(target_env = "musl"))]
 use crate::Result;
 #[cfg(not(target_env = "musl"))]
diff --git a/src/unistd.rs b/src/unistd.rs
index 2c89d77..7a4517e 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -29,9 +29,6 @@
           target_os = "linux", target_os = "openbsd"))]
 pub use self::setres::*;
 
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub use self::getres::*;
-
 /// User identifier
 ///
 /// Newtype pattern around `uid_t` (which is just alias). It prevents bugs caused by accidentally
@@ -41,7 +38,7 @@
 
 impl Uid {
     /// Creates `Uid` from raw `uid_t`.
-    pub const fn from_raw(uid: uid_t) -> Self {
+    pub fn from_raw(uid: uid_t) -> Self {
         Uid(uid)
     }
 
@@ -56,12 +53,12 @@
     }
 
     /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.)
-    pub const fn is_root(self) -> bool {
-        self.0 == ROOT.0
+    pub fn is_root(self) -> bool {
+        self == ROOT
     }
 
     /// Get the raw `uid_t` wrapped by `self`.
-    pub const fn as_raw(self) -> uid_t {
+    pub fn as_raw(self) -> uid_t {
         self.0
     }
 }
@@ -90,7 +87,7 @@
 
 impl Gid {
     /// Creates `Gid` from raw `gid_t`.
-    pub const fn from_raw(gid: gid_t) -> Self {
+    pub fn from_raw(gid: gid_t) -> Self {
         Gid(gid)
     }
 
@@ -105,7 +102,7 @@
     }
 
     /// Get the raw `gid_t` wrapped by `self`.
-    pub const fn as_raw(self) -> gid_t {
+    pub fn as_raw(self) -> gid_t {
         self.0
     }
 }
@@ -131,7 +128,7 @@
 
 impl Pid {
     /// Creates `Pid` from raw `pid_t`.
-    pub const fn from_raw(pid: pid_t) -> Self {
+    pub fn from_raw(pid: pid_t) -> Self {
         Pid(pid)
     }
 
@@ -146,7 +143,7 @@
     }
 
     /// Get the raw `pid_t` wrapped by `self`.
-    pub const fn as_raw(self) -> pid_t {
+    pub fn as_raw(self) -> pid_t {
         self.0
     }
 }
@@ -180,7 +177,10 @@
     /// Return `true` if this is the child process of the `fork()`
     #[inline]
     pub fn is_child(self) -> bool {
-        matches!(self, ForkResult::Child)
+        match self {
+            ForkResult::Child => true,
+            _ => false
+        }
     }
 
     /// Returns `true` if this is the parent process of the `fork()`
@@ -191,25 +191,20 @@
 }
 
 /// Create a new child process duplicating the parent process ([see
-/// fork(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)).
+/// fork(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)).
 ///
 /// After calling the fork system call (successfully) two processes will
 /// be created that are identical with the exception of their pid and the
 /// return value of this function.  As an example:
 ///
-/// ```
-/// use nix::{sys::wait::waitpid,unistd::{fork, ForkResult, write}};
+/// ```no_run
+/// use nix::unistd::{fork, ForkResult};
 ///
 /// match unsafe{fork()} {
 ///    Ok(ForkResult::Parent { child, .. }) => {
 ///        println!("Continuing execution in parent process, new child has pid: {}", child);
-///        waitpid(child, None).unwrap();
 ///    }
-///    Ok(ForkResult::Child) => {
-///        // Unsafe to use `println!` (or `unwrap`) here. See Safety.
-///        write(libc::STDOUT_FILENO, "I'm a new child process\n".as_bytes()).ok();
-///        unsafe { libc::_exit(0) };
-///    }
+///    Ok(ForkResult::Child) => println!("I'm a new child process"),
 ///    Err(_) => println!("Fork failed"),
 /// }
 /// ```
@@ -233,7 +228,7 @@
 /// Those functions are only a small subset of your operating system's API, so
 /// special care must be taken to only invoke code you can control and audit.
 ///
-/// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html
+/// [async-signal-safe]: http://man7.org/linux/man-pages/man7/signal-safety.7.html
 #[inline]
 pub unsafe fn fork() -> Result<ForkResult> {
     use self::ForkResult::*;
@@ -246,7 +241,7 @@
 }
 
 /// Get the pid of this process (see
-/// [getpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)).
+/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)).
 ///
 /// Since you are running code, there is always a pid to return, so there
 /// is no error case that needs to be handled.
@@ -256,7 +251,7 @@
 }
 
 /// Get the pid of this processes' parent (see
-/// [getpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)).
+/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)).
 ///
 /// There is always a parent pid to return, so there is no error case that needs
 /// to be handled.
@@ -266,7 +261,7 @@
 }
 
 /// Set a process group ID (see
-/// [setpgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)).
+/// [setpgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)).
 ///
 /// Set the process group id (PGID) of a particular process.  If a pid of zero
 /// is specified, then the pid of the calling process is used.  Process groups
@@ -286,14 +281,14 @@
 }
 
 /// Create new session and set process group id (see
-/// [setsid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)).
+/// [setsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)).
 #[inline]
 pub fn setsid() -> Result<Pid> {
     Errno::result(unsafe { libc::setsid() }).map(Pid)
 }
 
 /// Get the process group ID of a session leader
-/// [getsid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html).
+/// [getsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html).
 ///
 /// Obtain the process group ID of the process that is the session leader of the process specified
 /// by pid. If pid is zero, it specifies the calling process.
@@ -306,7 +301,7 @@
 
 
 /// Get the terminal foreground process group (see
-/// [tcgetpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)).
+/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)).
 ///
 /// Get the group process id (GPID) of the foreground process group on the
 /// terminal associated to file descriptor (FD).
@@ -316,7 +311,7 @@
     Errno::result(res).map(Pid)
 }
 /// Set the terminal foreground process group (see
-/// [tcgetpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)).
+/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)).
 ///
 /// Get the group process id (PGID) to the foreground process group on the
 /// terminal associated to file descriptor (FD).
@@ -328,7 +323,7 @@
 
 
 /// Get the group id of the calling process (see
-///[getpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)).
+///[getpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)).
 ///
 /// Get the process group id (PGID) of the calling process.
 /// According to the man page it is always successful.
@@ -338,7 +333,7 @@
 }
 
 /// Get the caller's thread ID (see
-/// [gettid(2)](https://man7.org/linux/man-pages/man2/gettid.2.html).
+/// [gettid(2)](http://man7.org/linux/man-pages/man2/gettid.2.html).
 ///
 /// This function is only available on Linux based systems.  In a single
 /// threaded process, the main thread will have the same ID as the process.  In
@@ -354,7 +349,7 @@
 }
 
 /// Create a copy of the specified file descriptor (see
-/// [dup(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
+/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
 ///
 /// The new file descriptor will be have a new index but refer to the same
 /// resource as the old file descriptor and the old and new file descriptors may
@@ -371,7 +366,7 @@
 }
 
 /// Create a copy of the specified file descriptor using the specified fd (see
-/// [dup(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
+/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
 ///
 /// This function behaves similar to `dup()` except that it will try to use the
 /// specified fd instead of allocating a new one.  See the man pages for more
@@ -384,7 +379,7 @@
 }
 
 /// Create a new copy of the specified file descriptor using the specified fd
-/// and flags (see [dup(2)](https://man7.org/linux/man-pages/man2/dup.2.html)).
+/// and flags (see [dup(2)](http://man7.org/linux/man-pages/man2/dup.2.html)).
 ///
 /// This function behaves similar to `dup2()` but allows for flags to be
 /// specified.
@@ -395,7 +390,7 @@
 #[inline]
 fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
     if oldfd == newfd {
-        return Err(Errno::EINVAL);
+        return Err(Error::Sys(Errno::EINVAL));
     }
 
     let fd = dup2(oldfd, newfd)?;
@@ -411,7 +406,7 @@
 }
 
 /// Change the current working directory of the calling process (see
-/// [chdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)).
+/// [chdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)).
 ///
 /// This function may fail in a number of different scenarios.  See the man
 /// pages for additional details on possible failure cases.
@@ -426,7 +421,7 @@
 
 /// Change the current working directory of the process to the one
 /// given as an open file descriptor (see
-/// [fchdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html)).
+/// [fchdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html)).
 ///
 /// This function may fail in a number of different scenarios.  See the man
 /// pages for additional details on possible failure cases.
@@ -438,7 +433,7 @@
     Errno::result(res).map(drop)
 }
 
-/// Creates new directory `path` with access rights `mode`.  (see [mkdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html))
+/// Creates new directory `path` with access rights `mode`.  (see [mkdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html))
 ///
 /// # Errors
 ///
@@ -455,13 +450,15 @@
 /// use nix::sys::stat;
 /// use tempfile::tempdir;
 ///
-/// let tmp_dir1 = tempdir().unwrap();
-/// let tmp_dir2 = tmp_dir1.path().join("new_dir");
+/// fn main() {
+///     let tmp_dir1 = tempdir().unwrap();
+///     let tmp_dir2 = tmp_dir1.path().join("new_dir");
 ///
-/// // create new directory and give read, write and execute rights to the owner
-/// match unistd::mkdir(&tmp_dir2, stat::Mode::S_IRWXU) {
-///    Ok(_) => println!("created {:?}", tmp_dir2),
-///    Err(err) => println!("Error creating directory: {}", err),
+///     // create new directory and give read, write and execute rights to the owner
+///     match unistd::mkdir(&tmp_dir2, stat::Mode::S_IRWXU) {
+///        Ok(_) => println!("created {:?}", tmp_dir2),
+///        Err(err) => println!("Error creating directory: {}", err),
+///     }
 /// }
 /// ```
 #[inline]
@@ -484,7 +481,7 @@
 /// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X)
 ///
 /// For a full list consult
-/// [posix specification](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html)
+/// [posix specification](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html)
 ///
 /// # Example
 ///
@@ -493,13 +490,15 @@
 /// use nix::sys::stat;
 /// use tempfile::tempdir;
 ///
-/// let tmp_dir = tempdir().unwrap();
-/// let fifo_path = tmp_dir.path().join("foo.pipe");
+/// fn main() {
+///     let tmp_dir = tempdir().unwrap();
+///     let fifo_path = tmp_dir.path().join("foo.pipe");
 ///
-/// // create new fifo and give read, write and execute rights to the owner
-/// match unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) {
-///    Ok(_) => println!("created {:?}", fifo_path),
-///    Err(err) => println!("Error creating fifo: {}", err),
+///     // create new fifo and give read, write and execute rights to the owner
+///     match unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) {
+///        Ok(_) => println!("created {:?}", fifo_path),
+///        Err(err) => println!("Error creating fifo: {}", err),
+///     }
 /// }
 /// ```
 #[inline]
@@ -520,7 +519,7 @@
 ///
 /// # References
 ///
-/// [mkfifoat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html).
+/// [mkfifoat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html).
 // mkfifoat is not implemented in OSX or android
 #[inline]
 #[cfg(not(any(
@@ -542,7 +541,7 @@
 /// If `dirfd` is `None`, then `path2` is relative to the current working
 /// directory. This is identical to `libc::symlink(path1, path2)`.
 ///
-/// See also [symlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
+/// See also [symlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
 #[cfg(not(target_os = "redox"))]
 pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
     path1: &P1,
@@ -569,7 +568,7 @@
     use std::cmp::min;
 
     if buf.capacity() >= limit {
-        return Err(Errno::ERANGE)
+        return Err(Error::Sys(Errno::ERANGE))
     }
 
     let capacity = min(buf.capacity() * 2, limit);
@@ -588,9 +587,11 @@
 /// ```rust
 /// use nix::unistd;
 ///
-/// // assume that we are allowed to get current directory
-/// let dir = unistd::getcwd().unwrap();
-/// println!("The current directory is {:?}", dir);
+/// fn main() {
+///     // assume that we are allowed to get current directory
+///     let dir = unistd::getcwd().unwrap();
+///     println!("The current directory is {:?}", dir);
+/// }
 /// ```
 #[inline]
 pub fn getcwd() -> Result<PathBuf> {
@@ -612,9 +613,9 @@
                 let error = Errno::last();
                 // ERANGE means buffer was too small to store directory name
                 if error != Errno::ERANGE {
-                    return Err(error);
+                    return Err(Error::Sys(error));
                 }
-           }
+            }
 
             // Trigger the internal buffer resizing logic.
             reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?;
@@ -623,8 +624,6 @@
 }
 
 /// Computes the raw UID and GID values to pass to a `*chown` call.
-// The cast is not unnecessary on all platforms.
-#[allow(clippy::unnecessary_cast)]
 fn chown_raw_ids(owner: Option<Uid>, group: Option<Gid>) -> (libc::uid_t, libc::gid_t) {
     // According to the POSIX specification, -1 is used to indicate that owner and group
     // are not to be changed.  Since uid_t and gid_t are unsigned types, we have to wrap
@@ -638,7 +637,7 @@
 
 /// Change the ownership of the file at `path` to be owned by the specified
 /// `owner` (user) and `group` (see
-/// [chown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html)).
+/// [chown(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html)).
 ///
 /// The owner/group for the provided path name will not be modified if `None` is
 /// provided for that argument.  Ownership change will be attempted for the path
@@ -694,7 +693,7 @@
 ///
 /// # References
 ///
-/// [fchownat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
+/// [fchownat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
 #[cfg(not(target_os = "redox"))]
 pub fn fchownat<P: ?Sized + NixPath>(
     dirfd: Option<RawFd>,
@@ -723,7 +722,7 @@
 }
 
 /// Replace the current process image with a new one (see
-/// [exec(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
+/// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
 ///
 /// See the `::nix::unistd::execve` system call for additional details.  `execv`
 /// performs the same action but does not allow for customization of the
@@ -736,12 +735,12 @@
         libc::execv(path.as_ptr(), args_p.as_ptr())
     };
 
-    Err(Errno::last())
+    Err(Error::Sys(Errno::last()))
 }
 
 
 /// Replace the current process image with a new one (see
-/// [execve(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
+/// [execve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
 ///
 /// The execve system call allows for another process to be "called" which will
 /// replace the current process image.  That is, this process becomes the new
@@ -761,12 +760,12 @@
         libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
     };
 
-    Err(Errno::last())
+    Err(Error::Sys(Errno::last()))
 }
 
 /// Replace the current process image with a new one and replicate shell `PATH`
 /// searching behavior (see
-/// [exec(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
+/// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
 ///
 /// See `::nix::unistd::execve` for additional details.  `execvp` behaves the
 /// same as execv except that it will examine the `PATH` environment variables
@@ -781,12 +780,12 @@
         libc::execvp(filename.as_ptr(), args_p.as_ptr())
     };
 
-    Err(Errno::last())
+    Err(Error::Sys(Errno::last()))
 }
 
 /// Replace the current process image with a new one and replicate shell `PATH`
 /// searching behavior (see
-/// [`execvpe(3)`](https://man7.org/linux/man-pages/man3/exec.3.html)).
+/// [`execvpe(3)`](http://man7.org/linux/man-pages/man3/exec.3.html)).
 ///
 /// This functions like a combination of `execvp(2)` and `execve(2)` to pass an
 /// environment and have a search path. See these two for additional
@@ -802,11 +801,11 @@
         libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
     };
 
-    Err(Errno::last())
+    Err(Error::Sys(Errno::last()))
 }
 
 /// Replace the current process image with a new one (see
-/// [fexecve(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)).
+/// [fexecve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)).
 ///
 /// The `fexecve` function allows for another process to be "called" which will
 /// replace the current process image.  That is, this process becomes the new
@@ -830,11 +829,11 @@
         libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr())
     };
 
-    Err(Errno::last())
+    Err(Error::Sys(Errno::last()))
 }
 
 /// Execute program relative to a directory file descriptor (see
-/// [execveat(2)](https://man7.org/linux/man-pages/man2/execveat.2.html)).
+/// [execveat(2)](http://man7.org/linux/man-pages/man2/execveat.2.html)).
 ///
 /// The `execveat` function allows for another process to be "called" which will
 /// replace the current process image.  That is, this process becomes the new
@@ -855,11 +854,11 @@
                       args_p.as_ptr(), env_p.as_ptr(), flags);
     };
 
-    Err(Errno::last())
+    Err(Error::Sys(Errno::last()))
 }
 
 /// Daemonize this process by detaching from the controlling terminal (see
-/// [daemon(3)](https://man7.org/linux/man-pages/man3/daemon.3.html)).
+/// [daemon(3)](http://man7.org/linux/man-pages/man3/daemon.3.html)).
 ///
 /// When a process is launched it is typically associated with a parent and it,
 /// in turn, by its controlling terminal/process.  In order for a process to run
@@ -886,18 +885,16 @@
 #[cfg(any(target_os = "android",
           target_os = "dragonfly",
           target_os = "freebsd",
-          target_os = "illumos",
           target_os = "linux",
           target_os = "netbsd",
-          target_os = "openbsd",
-          target_os = "solaris"))]
+          target_os = "openbsd"))]
 pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
     let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
     Errno::result(res).map(drop)
 }
 
 /// Set the system host name (see
-/// [sethostname(2)](https://man7.org/linux/man-pages/man2/gethostname.2.html)).
+/// [sethostname(2)](http://man7.org/linux/man-pages/man2/gethostname.2.html)).
 ///
 /// Given a name, attempt to update the system host name to the given string.
 /// On some systems, the host name is limited to as few as 64 bytes.  An error
@@ -909,10 +906,8 @@
     cfg_if! {
         if #[cfg(any(target_os = "dragonfly",
                      target_os = "freebsd",
-                     target_os = "illumos",
                      target_os = "ios",
-                     target_os = "macos",
-                     target_os = "solaris", ))] {
+                     target_os = "macos", ))] {
             type sethostname_len_t = c_int;
         } else {
             type sethostname_len_t = size_t;
@@ -927,7 +922,7 @@
 
 /// Get the host name and store it in the provided buffer, returning a pointer
 /// the `CStr` in that buffer on success (see
-/// [gethostname(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html)).
+/// [gethostname(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html)).
 ///
 /// This function call attempts to get the host name for the running system and
 /// store it in a provided buffer.  The buffer will be populated with bytes up
@@ -962,7 +957,7 @@
 /// `std::fs::File`.  Explicitly closing them with this method too can result in
 /// a double-close condition, which can cause confusing `EBADF` errors in
 /// seemingly unrelated code.  Caveat programmer.  See also
-/// [close(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html).
+/// [close(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html).
 ///
 /// # Examples
 ///
@@ -970,16 +965,20 @@
 /// use std::os::unix::io::AsRawFd;
 /// use nix::unistd::close;
 ///
-/// let f = tempfile::tempfile().unwrap();
-/// close(f.as_raw_fd()).unwrap();   // Bad!  f will also close on drop!
+/// fn main() {
+///     let f = tempfile::tempfile().unwrap();
+///     close(f.as_raw_fd()).unwrap();   // Bad!  f will also close on drop!
+/// }
 /// ```
 ///
 /// ```rust
 /// use std::os::unix::io::IntoRawFd;
 /// use nix::unistd::close;
 ///
-/// let f = tempfile::tempfile().unwrap();
-/// close(f.into_raw_fd()).unwrap(); // Good.  into_raw_fd consumes f
+/// fn main() {
+///     let f = tempfile::tempfile().unwrap();
+///     close(f.into_raw_fd()).unwrap(); // Good.  into_raw_fd consumes f
+/// }
 /// ```
 pub fn close(fd: RawFd) -> Result<()> {
     let res = unsafe { libc::close(fd) };
@@ -988,7 +987,7 @@
 
 /// Read from a raw file descriptor.
 ///
-/// See also [read(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html)
+/// See also [read(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html)
 pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
     let res = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };
 
@@ -997,7 +996,7 @@
 
 /// Write to a raw file descriptor.
 ///
-/// See also [write(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
+/// See also [write(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
 pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
     let res = unsafe { libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };
 
@@ -1020,28 +1019,20 @@
     /// Specify an offset relative to the next location in the file greater than or
     /// equal to offset that contains some data. If offset points to
     /// some data, then the file offset is set to offset.
-    #[cfg(any(target_os = "dragonfly",
-              target_os = "freebsd",
-              target_os = "illumos",
-              target_os = "linux",
-              target_os = "solaris"))]
+    #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
     SeekData = libc::SEEK_DATA,
     /// Specify an offset relative to the next hole in the file greater than
     /// or equal to offset. If offset points into the middle of a hole, then
     /// the file offset should be set to offset. If there is no hole past offset,
     /// then the file offset should be adjusted to the end of the file (i.e., there
     /// is an implicit hole at the end of any file).
-    #[cfg(any(target_os = "dragonfly",
-              target_os = "freebsd",
-              target_os = "illumos",
-              target_os = "linux",
-              target_os = "solaris"))]
+    #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
     SeekHole = libc::SEEK_HOLE
 }
 
 /// Move the read/write file offset.
 ///
-/// See also [lseek(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html)
+/// See also [lseek(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html)
 pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t> {
     let res = unsafe { libc::lseek(fd, offset, whence as i32) };
 
@@ -1057,14 +1048,14 @@
 
 /// Create an interprocess channel.
 ///
-/// See also [pipe(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
-pub fn pipe() -> std::result::Result<(RawFd, RawFd), Error> {
+/// See also [pipe(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
+pub fn pipe() -> Result<(RawFd, RawFd)> {
     unsafe {
         let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
 
         let res = libc::pipe(fds.as_mut_ptr() as *mut c_int);
 
-        Error::result(res)?;
+        Errno::result(res)?;
 
         Ok((fds.assume_init()[0], fds.assume_init()[1]))
     }
@@ -1075,22 +1066,20 @@
 /// The following flags are supported, and will be set atomically as the pipe is
 /// created:
 ///
-/// - `O_CLOEXEC`:    Set the close-on-exec flag for the new file descriptors.
-#[cfg_attr(target_os = "linux", doc = "- `O_DIRECT`: Create a pipe that performs I/O in \"packet\" mode.")]
-#[cfg_attr(target_os = "netbsd", doc = "- `O_NOSIGPIPE`: Return `EPIPE` instead of raising `SIGPIPE`.")]
-/// - `O_NONBLOCK`:   Set the non-blocking flag for the ends of the pipe.
+/// `O_CLOEXEC`:    Set the close-on-exec flag for the new file descriptors.  
+#[cfg_attr(target_os = "linux", doc = "`O_DIRECT`: Create a pipe that performs I/O in \"packet\" mode.  ")]
+#[cfg_attr(target_os = "netbsd", doc = "`O_NOSIGPIPE`: Return `EPIPE` instead of raising `SIGPIPE`.  ")]
+/// `O_NONBLOCK`:   Set the non-blocking flag for the ends of the pipe.
 ///
-/// See also [pipe(2)](https://man7.org/linux/man-pages/man2/pipe.2.html)
+/// See also [pipe(2)](http://man7.org/linux/man-pages/man2/pipe.2.html)
 #[cfg(any(target_os = "android",
           target_os = "dragonfly",
           target_os = "emscripten",
           target_os = "freebsd",
-          target_os = "illumos",
           target_os = "linux",
           target_os = "redox",
           target_os = "netbsd",
-          target_os = "openbsd",
-          target_os = "solaris"))]
+          target_os = "openbsd"))]
 pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
     let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
 
@@ -1106,7 +1095,7 @@
 /// Truncate a file to a specified length
 ///
 /// See also
-/// [truncate(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
+/// [truncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
 #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
 pub fn truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()> {
     let res = path.with_nix_path(|cstr| {
@@ -1121,7 +1110,7 @@
 /// Truncate a file to a specified length
 ///
 /// See also
-/// [ftruncate(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html)
+/// [ftruncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html)
 pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
     Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop)
 }
@@ -1135,9 +1124,9 @@
         } else {
             match Errno::last() {
                 Errno::ENOTTY => Ok(false),
-                err => Err(err),
+                err => Err(Error::Sys(err)),
             }
-       }
+        }
     }
 }
 
@@ -1160,7 +1149,7 @@
 /// process. If either `oldpath` or `newpath` is absolute, then `dirfd` is ignored.
 ///
 /// # References
-/// See also [linkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html)
+/// See also [linkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html)
 #[cfg(not(target_os = "redox"))] // RedoxFS does not support symlinks yet
 pub fn linkat<P: ?Sized + NixPath>(
     olddirfd: Option<RawFd>,
@@ -1196,7 +1185,7 @@
 
 /// Remove a directory entry
 ///
-/// See also [unlink(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
+/// See also [unlink(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
 pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
     let res = path.with_nix_path(|cstr| {
         unsafe {
@@ -1222,7 +1211,7 @@
 /// is performed.
 ///
 /// # References
-/// See also [unlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
+/// See also [unlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
 #[cfg(not(target_os = "redox"))]
 pub fn unlinkat<P: ?Sized + NixPath>(
     dirfd: Option<RawFd>,
@@ -1255,7 +1244,7 @@
 
 /// Commit filesystem caches to disk
 ///
-/// See also [sync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
+/// See also [sync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
 #[cfg(any(
     target_os = "dragonfly",
     target_os = "freebsd",
@@ -1269,7 +1258,7 @@
 
 /// Synchronize changes to a file
 ///
-/// See also [fsync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
+/// See also [fsync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
 #[inline]
 pub fn fsync(fd: RawFd) -> Result<()> {
     let res = unsafe { libc::fsync(fd) };
@@ -1280,14 +1269,12 @@
 /// Synchronize the data of a file
 ///
 /// See also
-/// [fdatasync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html)
+/// [fdatasync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html)
 // `fdatasync(2) is in POSIX, but in libc it is only defined in `libc::notbsd`.
 // TODO: exclude only Apple systems after https://github.com/rust-lang/libc/pull/211
 #[cfg(any(target_os = "linux",
           target_os = "android",
-          target_os = "emscripten",
-          target_os = "illumos",
-          target_os = "solaris"))]
+          target_os = "emscripten"))]
 #[inline]
 pub fn fdatasync(fd: RawFd) -> Result<()> {
     let res = unsafe { libc::fdatasync(fd) };
@@ -1297,7 +1284,7 @@
 
 /// Get a real user ID
 ///
-/// See also [getuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html)
+/// See also [getuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html)
 // POSIX requires that getuid is always successful, so no need to check return
 // value or errno.
 #[inline]
@@ -1307,7 +1294,7 @@
 
 /// Get the effective user ID
 ///
-/// See also [geteuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html)
+/// See also [geteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html)
 // POSIX requires that geteuid is always successful, so no need to check return
 // value or errno.
 #[inline]
@@ -1317,7 +1304,7 @@
 
 /// Get the real group ID
 ///
-/// See also [getgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html)
+/// See also [getgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html)
 // POSIX requires that getgid is always successful, so no need to check return
 // value or errno.
 #[inline]
@@ -1327,7 +1314,7 @@
 
 /// Get the effective group ID
 ///
-/// See also [getegid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html)
+/// See also [getegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html)
 // POSIX requires that getegid is always successful, so no need to check return
 // value or errno.
 #[inline]
@@ -1337,7 +1324,7 @@
 
 /// Set the effective user ID
 ///
-/// See also [seteuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html)
+/// See also [seteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html)
 #[inline]
 pub fn seteuid(euid: Uid) -> Result<()> {
     let res = unsafe { libc::seteuid(euid.into()) };
@@ -1347,7 +1334,7 @@
 
 /// Set the effective group ID
 ///
-/// See also [setegid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html)
+/// See also [setegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html)
 #[inline]
 pub fn setegid(egid: Gid) -> Result<()> {
     let res = unsafe { libc::setegid(egid.into()) };
@@ -1357,7 +1344,7 @@
 
 /// Set the user ID
 ///
-/// See also [setuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html)
+/// See also [setuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html)
 #[inline]
 pub fn setuid(uid: Uid) -> Result<()> {
     let res = unsafe { libc::setuid(uid.into()) };
@@ -1367,7 +1354,7 @@
 
 /// Set the group ID
 ///
-/// See also [setgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html)
+/// See also [setgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html)
 #[inline]
 pub fn setgid(gid: Gid) -> Result<()> {
     let res = unsafe { libc::setgid(gid.into()) };
@@ -1379,7 +1366,7 @@
 /// On both success and failure, this call returns the previous filesystem user
 /// ID of the caller.
 ///
-/// See also [setfsuid(2)](https://man7.org/linux/man-pages/man2/setfsuid.2.html)
+/// See also [setfsuid(2)](http://man7.org/linux/man-pages/man2/setfsuid.2.html)
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub fn setfsuid(uid: Uid) -> Uid {
     let prev_fsuid = unsafe { libc::setfsuid(uid.into()) };
@@ -1390,7 +1377,7 @@
 /// On both success and failure, this call returns the previous filesystem group
 /// ID of the caller.
 ///
-/// See also [setfsgid(2)](https://man7.org/linux/man-pages/man2/setfsgid.2.html)
+/// See also [setfsgid(2)](http://man7.org/linux/man-pages/man2/setfsgid.2.html)
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub fn setfsgid(gid: Gid) -> Gid {
     let prev_fsgid = unsafe { libc::setfsgid(gid.into()) };
@@ -1399,7 +1386,7 @@
 
 /// Get the list of supplementary group IDs of the calling process.
 ///
-/// [Further reading](https://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
+/// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
 ///
 /// **Note:** This function is not available for Apple platforms. On those
 /// platforms, checking group membership should be achieved via communication
@@ -1417,14 +1404,6 @@
     // Next, get the number of groups so we can size our Vec
     let ngroups = unsafe { libc::getgroups(0, ptr::null_mut()) };
 
-    // If there are no supplementary groups, return early.
-    // This prevents a potential buffer over-read if the number of groups
-    // increases from zero before the next call. It would return the total
-    // number of groups beyond the capacity of the buffer.
-    if ngroups == 0 {
-        return Ok(Vec::new());
-    }
-
     // Now actually get the groups. We try multiple times in case the number of
     // groups has changed since the first call to getgroups() and the buffer is
     // now too small.
@@ -1442,11 +1421,11 @@
                 unsafe { groups.set_len(s as usize) };
                 return Ok(groups);
             },
-            Err(Errno::EINVAL) => {
+            Err(Error::Sys(Errno::EINVAL)) => {
                 // EINVAL indicates that the buffer size was too
                 // small, resize it up to ngroups_max as limit.
                 reserve_double_buffer_size(&mut groups, ngroups_max)
-                    .or(Err(Errno::EINVAL))?;
+                    .or(Err(Error::Sys(Errno::EINVAL)))?;
             },
             Err(e) => return Err(e)
         }
@@ -1455,7 +1434,7 @@
 
 /// Set the list of supplementary group IDs for the calling process.
 ///
-/// [Further reading](https://man7.org/linux/man-pages/man2/getgroups.2.html)
+/// [Further reading](http://man7.org/linux/man-pages/man2/getgroups.2.html)
 ///
 /// **Note:** This function is not available for Apple platforms. On those
 /// platforms, group membership management should be achieved via communication
@@ -1489,11 +1468,9 @@
     cfg_if! {
         if #[cfg(any(target_os = "dragonfly",
                      target_os = "freebsd",
-                     target_os = "illumos",
                      target_os = "ios",
                      target_os = "macos",
                      target_os = "netbsd",
-                     target_os = "illumos",
                      target_os = "openbsd"))] {
             type setgroups_ngroups_t = c_int;
         } else {
@@ -1515,7 +1492,7 @@
 /// Gets the group IDs of all groups that `user` is a member of. The additional
 /// group `group` is also added to the list.
 ///
-/// [Further reading](https://man7.org/linux/man-pages/man3/getgrouplist.3.html)
+/// [Further reading](http://man7.org/linux/man-pages/man3/getgrouplist.3.html)
 ///
 /// **Note:** This function is not available for Apple platforms. On those
 /// platforms, checking group membership should be achieved via communication
@@ -1530,17 +1507,15 @@
 /// and `setgroups()`. Additionally, while some implementations will return a
 /// partial list of groups when `NGROUPS_MAX` is exceeded, this implementation
 /// will only ever return the complete list or else an error.
-#[cfg(not(any(target_os = "illumos",
-              target_os = "ios",
-              target_os = "macos",
-              target_os = "redox")))]
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
 pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
     let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
         Ok(Some(n)) => n as c_int,
         Ok(None) | Err(_) => <c_int>::max_value(),
     };
     use std::cmp::min;
-    let mut groups = Vec::<Gid>::with_capacity(min(ngroups_max, 8) as usize);
+    let mut ngroups = min(ngroups_max, 8);
+    let mut groups = Vec::<Gid>::with_capacity(ngroups as usize);
     cfg_if! {
         if #[cfg(any(target_os = "ios", target_os = "macos"))] {
             type getgrouplist_group_t = c_int;
@@ -1550,7 +1525,6 @@
     }
     let gid: gid_t = group.into();
     loop {
-        let mut ngroups = groups.capacity() as i32;
         let ret = unsafe {
             libc::getgrouplist(user.as_ptr(),
                                gid as getgrouplist_group_t,
@@ -1568,7 +1542,7 @@
             // groups as possible, but Linux manpages do not mention this
             // behavior.
             reserve_double_buffer_size(&mut groups, ngroups_max as usize)
-                .map_err(|_| Errno::EINVAL)?;
+                .or_else(|_| Err(Error::invalid_argument()))?;
         }
     }
 }
@@ -1579,7 +1553,7 @@
 /// that `user` is a member of. The additional group `group` is also added to
 /// the list.
 ///
-/// [Further reading](https://man7.org/linux/man-pages/man3/initgroups.3.html)
+/// [Further reading](http://man7.org/linux/man-pages/man3/initgroups.3.html)
 ///
 /// **Note:** This function is not available for Apple platforms. On those
 /// platforms, group membership management should be achieved via communication
@@ -1628,7 +1602,7 @@
 
 /// Suspend the thread until a signal is received.
 ///
-/// See also [pause(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
+/// See also [pause(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
 #[inline]
 #[cfg(not(target_os = "redox"))]
 pub fn pause() {
@@ -1673,18 +1647,17 @@
     //! extern fn signal_handler(_: nix::libc::c_int) { }
     //! let sa = SigAction::new(
     //!     SigHandler::Handler(signal_handler),
-    //!     SaFlags::SA_RESTART,
+    //!     SaFlags::empty(),
     //!     SigSet::empty()
     //! );
     //! unsafe {
     //!     sigaction(Signal::SIGALRM, &sa);
     //! }
     //!
-    //! let start = Instant::now();
-    //!
     //! // Set an alarm for 1 second from now.
     //! alarm::set(1);
     //!
+    //! let start = Instant::now();
     //! // Pause the process until the alarm signal is received.
     //! let mut sigset = SigSet::empty();
     //! sigset.add(Signal::SIGALRM);
@@ -1695,7 +1668,7 @@
     //!
     //! # References
     //!
-    //! See also [alarm(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
+    //! See also [alarm(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
 
     /// Schedule an alarm signal.
     ///
@@ -1725,7 +1698,7 @@
 
 /// Suspend execution for an interval of time
 ///
-/// See also [sleep(2)](https://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
+/// See also [sleep(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
 // Per POSIX, does not fail
 #[inline]
 pub fn sleep(seconds: c_uint) -> c_uint {
@@ -1765,7 +1738,7 @@
 /// Err is returned either if no temporary filename could be created or the template doesn't
 /// end with XXXXXX
 ///
-/// See also [mkstemp(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html)
+/// See also [mkstemp(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html)
 ///
 /// # Example
 ///
@@ -1796,7 +1769,7 @@
 /// Variable names for `pathconf`
 ///
 /// Nix uses the same naming convention for these variables as the
-/// [getconf(1)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
+/// [getconf(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
 /// That is, `PathconfVar` variables have the same name as the abstract
 /// variables  shown in the `pathconf(2)` man page.  Usually, it's the same as
 /// the C variable name without the leading `_PC_`.
@@ -1806,12 +1779,11 @@
 ///
 /// # References
 ///
-/// - [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html)
-/// - [limits.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
-/// - [unistd.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
+/// - [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html)
+/// - [limits.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
+/// - [unistd.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 #[repr(i32)]
-#[non_exhaustive]
 pub enum PathconfVar {
     #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux",
               target_os = "netbsd", target_os = "openbsd", target_os = "redox"))]
@@ -1837,9 +1809,8 @@
     /// Maximum number of bytes that is guaranteed to be atomic when writing to
     /// a pipe.
     PIPE_BUF = libc::_PC_PIPE_BUF,
-    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "illumos",
-              target_os = "linux", target_os = "netbsd", target_os = "openbsd",
-              target_os = "redox", target_os = "solaris"))]
+    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "linux",
+              target_os = "netbsd", target_os = "openbsd", target_os = "redox"))]
     /// Symbolic links can be created.
     POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
@@ -1865,8 +1836,8 @@
     ///  Recommended file transfer buffer alignment.
     POSIX_REC_XFER_ALIGN = libc::_PC_REC_XFER_ALIGN,
     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-              target_os = "illumos", target_os = "linux", target_os = "netbsd",
-              target_os = "openbsd", target_os = "redox", target_os = "solaris"))]
+              target_os = "linux", target_os = "netbsd", target_os = "openbsd",
+              target_os = "redox"))]
     /// Maximum number of bytes in a symbolic link.
     SYMLINK_MAX = libc::_PC_SYMLINK_MAX,
     /// The use of `chown` and `fchown` is restricted to a process with
@@ -1880,20 +1851,18 @@
     /// disable terminal special character handling.
     _POSIX_VDISABLE = libc::_PC_VDISABLE,
     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-              target_os = "illumos", target_os = "linux", target_os = "openbsd",
-              target_os = "redox", target_os = "solaris"))]
+              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
     /// Asynchronous input or output operations may be performed for the
     /// associated file.
     _POSIX_ASYNC_IO = libc::_PC_ASYNC_IO,
     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-              target_os = "illumos", target_os = "linux", target_os = "openbsd",
-              target_os = "redox", target_os = "solaris"))]
+              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
     /// Prioritized input or output operations may be performed for the
     /// associated file.
     _POSIX_PRIO_IO = libc::_PC_PRIO_IO,
     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-              target_os = "illumos", target_os = "linux", target_os = "netbsd",
-              target_os = "openbsd", target_os = "redox", target_os = "solaris"))]
+              target_os = "linux", target_os = "netbsd", target_os = "openbsd",
+              target_os = "redox"))]
     /// Synchronized input or output operations may be performed for the
     /// associated file.
     _POSIX_SYNC_IO = libc::_PC_SYNC_IO,
@@ -1903,7 +1872,7 @@
 }
 
 /// Like `pathconf`, but works with file descriptors instead of paths (see
-/// [fpathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
+/// [fpathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
 ///
 /// # Parameters
 ///
@@ -1927,7 +1896,7 @@
         if errno::errno() == 0 {
             Ok(None)
         } else {
-            Err(Errno::last())
+            Err(Error::Sys(Errno::last()))
         }
     } else {
         Ok(Some(raw))
@@ -1935,12 +1904,12 @@
 }
 
 /// Get path-dependent configurable system variables (see
-/// [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
+/// [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
 ///
 /// Returns the value of a path-dependent configurable system variable.  Most
 /// supported variables also have associated compile-time constants, but POSIX
 /// allows their values to change at runtime.  There are generally two types of
-/// `pathconf` variables: options and limits.  See [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details.
+/// `pathconf` variables: options and limits.  See [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details.
 ///
 /// # Parameters
 ///
@@ -1966,7 +1935,7 @@
         if errno::errno() == 0 {
             Ok(None)
         } else {
-            Err(Errno::last())
+            Err(Error::Sys(Errno::last()))
         }
     } else {
         Ok(Some(raw))
@@ -1976,7 +1945,7 @@
 /// Variable names for `sysconf`
 ///
 /// Nix uses the same naming convention for these variables as the
-/// [getconf(1)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
+/// [getconf(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
 /// That is, `SysconfVar` variables have the same name as the abstract variables
 /// shown in the `sysconf(3)` man page.  Usually, it's the same as the C
 /// variable name without the leading `_SC_`.
@@ -1986,12 +1955,11 @@
 ///
 /// # References
 ///
-/// - [sysconf(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html)
-/// - [unistd.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
-/// - [limits.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
+/// - [sysconf(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html)
+/// - [unistd.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html)
+/// - [limits.h](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 #[repr(i32)]
-#[non_exhaustive]
 pub enum SysconfVar {
     /// Maximum number of I/O operations in a single list I/O call supported by
     /// the implementation.
@@ -2039,9 +2007,9 @@
     /// the expr utility.
     #[cfg(not(target_os = "redox"))]
     EXPR_NEST_MAX = libc::_SC_EXPR_NEST_MAX,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos",
-              target_os = "ios", target_os="linux", target_os = "macos",
-              target_os="netbsd", target_os="openbsd", target_os = "solaris"))]
+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+              target_os="linux", target_os = "macos", target_os="netbsd",
+              target_os="openbsd"))]
     /// Maximum length of a host name (not including the terminating null) as
     /// returned from the `gethostname` function
     HOST_NAME_MAX = libc::_SC_HOST_NAME_MAX,
@@ -2078,30 +2046,29 @@
               target_os="linux", target_os = "macos", target_os="openbsd"))]
     /// The implementation supports the Advisory Information option.
     _POSIX_ADVISORY_INFO = libc::_SC_ADVISORY_INFO,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos",
-              target_os = "ios", target_os="linux", target_os = "macos",
-              target_os="netbsd", target_os="openbsd", target_os = "solaris"))]
+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+              target_os="linux", target_os = "macos", target_os="netbsd",
+              target_os="openbsd"))]
     /// The implementation supports barriers.
     _POSIX_BARRIERS = libc::_SC_BARRIERS,
     /// The implementation supports asynchronous input and output.
     #[cfg(not(target_os = "redox"))]
     _POSIX_ASYNCHRONOUS_IO = libc::_SC_ASYNCHRONOUS_IO,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos",
-              target_os = "ios", target_os="linux", target_os = "macos",
-              target_os="netbsd", target_os="openbsd", target_os = "solaris"))]
+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+              target_os="linux", target_os = "macos", target_os="netbsd",
+              target_os="openbsd"))]
     /// The implementation supports clock selection.
     _POSIX_CLOCK_SELECTION = libc::_SC_CLOCK_SELECTION,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos",
-              target_os = "ios", target_os="linux", target_os = "macos",
-              target_os="netbsd", target_os="openbsd", target_os = "solaris"))]
+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+              target_os="linux", target_os = "macos", target_os="netbsd",
+              target_os="openbsd"))]
     /// The implementation supports the Process CPU-Time Clocks option.
     _POSIX_CPUTIME = libc::_SC_CPUTIME,
     /// The implementation supports the File Synchronization option.
     #[cfg(not(target_os = "redox"))]
     _POSIX_FSYNC = libc::_SC_FSYNC,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos",
-              target_os = "ios", target_os="linux", target_os = "macos",
-              target_os="openbsd", target_os = "solaris"))]
+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+              target_os="linux", target_os = "macos", target_os="openbsd"))]
     /// The implementation supports the IPv6 option.
     _POSIX_IPV6 = libc::_SC_IPV6,
     /// The implementation supports job control.
@@ -2126,21 +2093,20 @@
     #[cfg(not(target_os = "redox"))]
     _POSIX_MONOTONIC_CLOCK = libc::_SC_MONOTONIC_CLOCK,
     #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-              target_os = "illumos", target_os = "ios", target_os="linux",
-              target_os = "macos", target_os="openbsd", target_os = "solaris"))]
+              target_os = "ios", target_os="linux", target_os = "macos",
+              target_os="openbsd"))]
     /// The implementation supports the Prioritized Input and Output option.
     _POSIX_PRIORITIZED_IO = libc::_SC_PRIORITIZED_IO,
     /// The implementation supports the Process Scheduling option.
     #[cfg(not(target_os = "redox"))]
     _POSIX_PRIORITY_SCHEDULING = libc::_SC_PRIORITY_SCHEDULING,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos",
-              target_os = "ios", target_os="linux", target_os = "macos",
-              target_os="openbsd", target_os = "solaris"))]
+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+              target_os="linux", target_os = "macos", target_os="openbsd"))]
     /// The implementation supports the Raw Sockets option.
     _POSIX_RAW_SOCKETS = libc::_SC_RAW_SOCKETS,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos",
-              target_os = "ios", target_os="linux", target_os = "macos",
-              target_os="netbsd", target_os="openbsd", target_os = "solaris"))]
+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+              target_os="linux", target_os = "macos", target_os="netbsd",
+              target_os="openbsd"))]
     /// The implementation supports read-write locks.
     _POSIX_READER_WRITER_LOCKS = libc::_SC_READER_WRITER_LOCKS,
     #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd",
@@ -2148,9 +2114,9 @@
               target_os = "openbsd"))]
     /// The implementation supports realtime signals.
     _POSIX_REALTIME_SIGNALS = libc::_SC_REALTIME_SIGNALS,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos",
-              target_os = "ios", target_os="linux", target_os = "macos",
-              target_os="netbsd", target_os="openbsd", target_os = "solaris"))]
+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+              target_os="linux", target_os = "macos", target_os="netbsd",
+              target_os="openbsd"))]
     /// The implementation supports the Regular Expression Handling option.
     _POSIX_REGEXP = libc::_SC_REGEXP,
     /// Each process has a saved set-user-ID and a saved set-group-ID.
@@ -2442,7 +2408,7 @@
 }
 
 /// Get configurable system variables (see
-/// [sysconf(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html))
+/// [sysconf(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html))
 ///
 /// Returns the value of a configurable system variable.  Most supported
 /// variables also have associated compile-time constants, but POSIX
@@ -2466,7 +2432,7 @@
         if errno::errno() == 0 {
             Ok(None)
         } else {
-            Err(Errno::last())
+            Err(Error::Sys(Errno::last()))
         }
     } else {
         Ok(Some(raw))
@@ -2500,7 +2466,7 @@
     use super::{Uid, Gid};
 
     /// Sets the real, effective, and saved uid.
-    /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html))
+    /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
     ///
     /// * `ruid`: real user id
     /// * `euid`: effective user id
@@ -2516,7 +2482,7 @@
     }
 
     /// Sets the real, effective, and saved gid.
-    /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html))
+    /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
     ///
     /// * `rgid`: real group id
     /// * `egid`: effective group id
@@ -2532,67 +2498,6 @@
     }
 }
 
-#[cfg(any(target_os = "android", target_os = "linux"))]
-mod getres {
-    use crate::Result;
-    use crate::errno::Errno;
-    use super::{Uid, Gid};
-
-    /// Real, effective and saved user IDs.
-    #[derive(Debug, Copy, Clone, Eq, PartialEq)]
-    pub struct ResUid {
-        pub real: Uid,
-        pub effective: Uid,
-        pub saved: Uid
-    }
-
-    /// Real, effective and saved group IDs.
-    #[derive(Debug, Copy, Clone, Eq, PartialEq)]
-    pub struct ResGid {
-        pub real: Gid,
-        pub effective: Gid,
-        pub saved: Gid
-    }
-
-    /// Gets the real, effective, and saved user IDs.
-    ///
-    /// ([see getresuid(2)](http://man7.org/linux/man-pages/man2/getresuid.2.html))
-    ///
-    /// #Returns
-    ///
-    /// - `Ok((Uid, Uid, Uid))`: tuple of real, effective and saved uids on success.
-    /// - `Err(x)`: libc error code on failure.
-    ///
-    #[inline]
-    pub fn getresuid() -> Result<ResUid> {
-        let mut ruid = libc::uid_t::max_value();
-        let mut euid = libc::uid_t::max_value();
-        let mut suid = libc::uid_t::max_value();
-        let res = unsafe { libc::getresuid(&mut ruid, &mut euid, &mut suid) };
-
-        Errno::result(res).map(|_| ResUid{ real: Uid(ruid), effective: Uid(euid), saved: Uid(suid) })
-    }
-
-    /// Gets the real, effective, and saved group IDs.
-    ///
-    /// ([see getresgid(2)](http://man7.org/linux/man-pages/man2/getresgid.2.html))
-    ///
-    /// #Returns
-    ///
-    /// - `Ok((Gid, Gid, Gid))`: tuple of real, effective and saved gids on success.
-    /// - `Err(x)`: libc error code on failure.
-    ///
-    #[inline]
-    pub fn getresgid() -> Result<ResGid> {
-        let mut rgid = libc::gid_t::max_value();
-        let mut egid = libc::gid_t::max_value();
-        let mut sgid = libc::gid_t::max_value();
-        let res = unsafe { libc::getresgid(&mut rgid, &mut egid, &mut sgid) };
-
-        Errno::result(res).map(|_| ResGid { real: Gid(rgid), effective: Gid(egid), saved: Gid(sgid) } )
-    }
-}
-
 libc_bitflags!{
     /// Options for access()
     pub struct AccessFlags : c_int {
@@ -2608,7 +2513,7 @@
 }
 
 /// Checks the file named by `path` for accessibility according to the flags given by `amode`
-/// See [access(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html)
+/// See [access(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html)
 pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
     let res = path.with_nix_path(|cstr| {
         unsafe {
@@ -2636,32 +2541,23 @@
     /// Group ID
     pub gid: Gid,
     /// User information
-    #[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
+    #[cfg(not(target_os = "android"))]
     pub gecos: CString,
     /// Home directory
     pub dir: PathBuf,
     /// Path to shell
     pub shell: PathBuf,
     /// Login class
-    #[cfg(not(any(target_os = "android",
-                  target_os = "fuchsia",
-                  target_os = "illumos",
-                  target_os = "linux",
-                  target_os = "solaris")))]
+    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
+                  target_os = "linux")))]
     pub class: CString,
     /// Last password change
-    #[cfg(not(any(target_os = "android",
-                  target_os = "fuchsia",
-                  target_os = "illumos",
-                  target_os = "linux",
-                  target_os = "solaris")))]
+    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
+                  target_os = "linux")))]
     pub change: libc::time_t,
     /// Expiration time of account
-    #[cfg(not(any(target_os = "android",
-                  target_os = "fuchsia",
-                  target_os = "illumos",
-                  target_os = "linux",
-                  target_os = "solaris")))]
+    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
+                  target_os = "linux")))]
     pub expire: libc::time_t
 }
 
@@ -2672,29 +2568,20 @@
             User {
                 name: CStr::from_ptr((*pw).pw_name).to_string_lossy().into_owned(),
                 passwd: CString::new(CStr::from_ptr((*pw).pw_passwd).to_bytes()).unwrap(),
-                #[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
+                #[cfg(not(target_os = "android"))]
                 gecos: CString::new(CStr::from_ptr((*pw).pw_gecos).to_bytes()).unwrap(),
                 dir: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_dir).to_bytes())),
                 shell: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_shell).to_bytes())),
                 uid: Uid::from_raw((*pw).pw_uid),
                 gid: Gid::from_raw((*pw).pw_gid),
-                #[cfg(not(any(target_os = "android",
-                              target_os = "fuchsia",
-                              target_os = "illumos",
-                              target_os = "linux",
-                              target_os = "solaris")))]
+                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
+                              target_os = "linux")))]
                 class: CString::new(CStr::from_ptr((*pw).pw_class).to_bytes()).unwrap(),
-                #[cfg(not(any(target_os = "android",
-                              target_os = "fuchsia",
-                              target_os = "illumos",
-                              target_os = "linux",
-                              target_os = "solaris")))]
+                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
+                              target_os = "linux")))]
                 change: (*pw).pw_change,
-                #[cfg(not(any(target_os = "android",
-                              target_os = "fuchsia",
-                              target_os = "illumos",
-                              target_os = "linux",
-                              target_os = "solaris")))]
+                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
+                              target_os = "linux")))]
                 expire: (*pw).pw_expire
             }
         }
@@ -2702,58 +2589,6 @@
 }
 
 #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-impl From<User> for libc::passwd {
-    fn from(u: User) -> Self {
-        let name = match CString::new(u.name) {
-            Ok(n) => n.into_raw(),
-            Err(_) => CString::new("").unwrap().into_raw(),
-        };
-        let dir = match u.dir.into_os_string().into_string() {
-            Ok(s) => CString::new(s.as_str()).unwrap().into_raw(),
-            Err(_) => CString::new("").unwrap().into_raw(),
-        };
-        let shell = match u.shell.into_os_string().into_string() {
-            Ok(s) => CString::new(s.as_str()).unwrap().into_raw(),
-            Err(_) => CString::new("").unwrap().into_raw(),
-        };
-        Self {
-            pw_name: name,
-            pw_passwd: u.passwd.into_raw(),
-            #[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
-            pw_gecos: u.gecos.into_raw(),
-            pw_dir: dir,
-            pw_shell: shell,
-            pw_uid: u.uid.0,
-            pw_gid: u.gid.0,
-            #[cfg(not(any(target_os = "android",
-                          target_os = "fuchsia",
-                          target_os = "illumos",
-                          target_os = "linux",
-                          target_os = "solaris")))]
-            pw_class: u.class.into_raw(),
-            #[cfg(not(any(target_os = "android",
-                          target_os = "fuchsia",
-                          target_os = "illumos",
-                          target_os = "linux",
-                          target_os = "solaris")))]
-            pw_change: u.change,
-            #[cfg(not(any(target_os = "android",
-                          target_os = "fuchsia",
-                          target_os = "illumos",
-                          target_os = "linux",
-                          target_os = "solaris")))]
-            pw_expire: u.expire,
-            #[cfg(target_os = "illumos")]
-            pw_age: CString::new("").unwrap().into_raw(),
-            #[cfg(target_os = "illumos")]
-            pw_comment: CString::new("").unwrap().into_raw(),
-            #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-            pw_fields: 0,
-        }
-    }
-}
-
-#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
 impl User {
     fn from_anything<F>(f: F) -> Result<Option<Self>>
     where
@@ -2762,10 +2597,10 @@
               libc::size_t,
               *mut *mut libc::passwd) -> libc::c_int
     {
-        let buflimit = 1048576;
+        let buflimit = 16384;
         let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) {
             Ok(Some(n)) => n as usize,
-            Ok(None) | Err(_) => 16384,
+            Ok(None) | Err(_) => buflimit as usize,
         };
 
         let mut cbuf = Vec::with_capacity(bufsize);
@@ -2785,7 +2620,7 @@
                 // Trigger the internal buffer resizing logic.
                 reserve_double_buffer_size(&mut cbuf, buflimit)?;
             } else {
-                return Err(Errno::last());
+                return Err(Error::Sys(Errno::last()));
             }
         }
     }
@@ -2793,7 +2628,7 @@
     /// Get a user by UID.
     ///
     /// Internally, this function calls
-    /// [getpwuid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
+    /// [getpwuid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
     ///
     /// # Examples
     ///
@@ -2812,7 +2647,7 @@
     /// Get a user by name.
     ///
     /// Internally, this function calls
-    /// [getpwnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
+    /// [getpwnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
     ///
     /// # Examples
     ///
@@ -2883,10 +2718,10 @@
               libc::size_t,
               *mut *mut libc::group) -> libc::c_int
     {
-        let buflimit = 1048576;
+        let buflimit = 16384;
         let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) {
             Ok(Some(n)) => n as usize,
-            Ok(None) | Err(_) => 16384,
+            Ok(None) | Err(_) => buflimit as usize,
         };
 
         let mut cbuf = Vec::with_capacity(bufsize);
@@ -2906,7 +2741,7 @@
                 // Trigger the internal buffer resizing logic.
                 reserve_double_buffer_size(&mut cbuf, buflimit)?;
             } else {
-                return Err(Errno::last());
+                return Err(Error::Sys(Errno::last()));
             }
         }
     }
@@ -2914,7 +2749,7 @@
     /// Get a group by GID.
     ///
     /// Internally, this function calls
-    /// [getgrgid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
+    /// [getgrgid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
     ///
     /// # Examples
     ///
@@ -2935,7 +2770,7 @@
     /// Get a group by name.
     ///
     /// Internally, this function calls
-    /// [getgrnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
+    /// [getgrnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
     ///
     /// # Examples
     ///
@@ -2956,7 +2791,7 @@
 }
 
 /// Get the name of the terminal device that is open on file descriptor fd
-/// (see [`ttyname(3)`](https://man7.org/linux/man-pages/man3/ttyname.3.html)).
+/// (see [`ttyname(3)`](http://man7.org/linux/man-pages/man3/ttyname.3.html)).
 #[cfg(not(target_os = "fuchsia"))]
 pub fn ttyname(fd: RawFd) -> Result<PathBuf> {
     const PATH_MAX: usize = libc::PATH_MAX as usize;
@@ -2965,7 +2800,7 @@
 
     let ret = unsafe { libc::ttyname_r(fd, c_buf, buf.len()) };
     if ret != 0 {
-        return Err(Errno::from_i32(ret));
+        return Err(Error::Sys(Errno::from_i32(ret)));
     }
 
     let nul = buf.iter().position(|c| *c == b'\0').unwrap();
diff --git a/test/common/mod.rs b/test/common/mod.rs
index 84a0b4f..a871b47 100644
--- a/test/common/mod.rs
+++ b/test/common/mod.rs
@@ -14,33 +14,19 @@
 cfg_if! {
     if #[cfg(any(target_os = "android", target_os = "linux"))] {
         #[macro_export] macro_rules! require_capability {
-            ($name:expr, $capname:ident) => {
+            ($capname:ident) => {
                 use ::caps::{Capability, CapSet, has_cap};
 
                 if !has_cap(None, CapSet::Effective, Capability::$capname)
                     .unwrap()
                 {
-                    skip!("{} requires capability {}. Skipping test.", $name, Capability::$capname);
+                    skip!("Insufficient capabilities. Skipping test.");
                 }
             }
         }
     } else if #[cfg(not(target_os = "redox"))] {
         #[macro_export] macro_rules! require_capability {
-            ($name:expr, $capname:ident) => {}
-        }
-    }
-}
-
-/// Skip the test if we don't have the ability to mount file systems.
-#[cfg(target_os = "freebsd")]
-#[macro_export] macro_rules! require_mount {
-    ($name:expr) => {
-        use ::sysctl::CtlValue;
-        use nix::unistd::Uid;
-
-        if !Uid::current().is_root() && CtlValue::Int(0) == ::sysctl::value("vfs.usermount").unwrap()
-        {
-            skip!("{} requires the ability to mount file systems. Skipping test.", $name);
+            ($capname:ident) => {}
         }
     }
 }
@@ -128,8 +114,8 @@
                 let mut version = Version::parse(fixed_release).unwrap();
 
                 //Keep only numeric parts
-                version.pre = semver::Prerelease::EMPTY;
-                version.build = semver::BuildMetadata::EMPTY;
+                version.pre.clear();
+                version.build.clear();
 
                 if !version_requirement.matches(&version) {
                     skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`",
diff --git a/test/sys/mod.rs b/test/sys/mod.rs
index e73d9b1..14b0378 100644
--- a/test/sys/mod.rs
+++ b/test/sys/mod.rs
@@ -11,8 +11,6 @@
           target_os = "macos",
           target_os = "netbsd"))]
 mod test_aio;
-#[cfg(not(target_os = "redox"))]
-mod test_mman;
 #[cfg(target_os = "linux")]
 mod test_signalfd;
 #[cfg(not(target_os = "redox"))]
diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs
index 80cd053..3878da9 100644
--- a/test/sys/test_aio.rs
+++ b/test/sys/test_aio.rs
@@ -1,5 +1,6 @@
+use bytes::{Bytes, BytesMut};
 use libc::{c_int, c_void};
-use nix::Result;
+use nix::{Error, Result};
 use nix::errno::*;
 use nix::sys::aio::*;
 use nix::sys::signal::{SaFlags, SigAction, sigaction, SigevNotify, SigHandler, Signal, SigSet};
@@ -7,26 +8,15 @@
 use std::io::{Write, Read, Seek, SeekFrom};
 use std::ops::Deref;
 use std::os::unix::io::AsRawFd;
-use std::pin::Pin;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::{thread, time};
 use tempfile::tempfile;
 
 // Helper that polls an AioCb for completion or error
-fn poll_aio(aiocb: &mut Pin<Box<AioCb>>) -> Result<()> {
+fn poll_aio(aiocb: &mut AioCb) -> Result<()> {
     loop {
         let err = aiocb.error();
-        if err != Err(Errno::EINPROGRESS) { return err; };
-        thread::sleep(time::Duration::from_millis(10));
-    }
-}
-
-// Helper that polls a component of an LioCb for completion or error
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-fn poll_lio(liocb: &mut LioCb, i: usize) -> Result<()> {
-    loop {
-        let err = liocb.error(i);
-        if err != Err(Errno::EINPROGRESS) { return err; };
+        if err != Err(Error::from(Errno::EINPROGRESS)) { return err; };
         thread::sleep(time::Duration::from_millis(10));
     }
 }
@@ -70,7 +60,7 @@
                             LioOpcode::LIO_NOP);
     aiocb.write().unwrap();
     let err = aiocb.error();
-    assert!(err == Ok(()) || err == Err(Errno::EINPROGRESS));
+    assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS)));
 
     let cancelstat = aiocb.cancel();
     assert!(cancelstat.is_ok());
@@ -95,7 +85,7 @@
                             LioOpcode::LIO_NOP);
     aiocb.write().unwrap();
     let err = aiocb.error();
-    assert!(err == Ok(()) || err == Err(Errno::EINPROGRESS));
+    assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS)));
 
     let cancelstat = aio_cancel_all(f.as_raw_fd());
     assert!(cancelstat.is_ok());
@@ -142,7 +132,9 @@
 }
 
 #[test]
-// On Cirrus on Linux, this test fails due to a glibc bug.
+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
+// On Travis, aio_suspend hits an assertion within glibc.  This is either a bug
+// in Travis's version of glibc or Linux.  Either way, we must skip the test.
 // https://github.com/nix-rust/nix/issues/1099
 #[cfg_attr(target_os = "linux", ignore)]
 // On Cirrus, aio_suspend is failing with EINVAL
@@ -174,16 +166,16 @@
     rcb.read().unwrap();
     loop {
         {
-            let cbbuf = [wcb.as_ref(), rcb.as_ref()];
+            let cbbuf = [&wcb, &rcb];
             let r = aio_suspend(&cbbuf[..], Some(timeout));
             match r {
-                Err(Errno::EINTR) => continue,
+                Err(Error::Sys(Errno::EINTR)) => continue,
                 Err(e) => panic!("aio_suspend returned {:?}", e),
                 Ok(_) => ()
             };
         }
-        if rcb.error() != Err(Errno::EINPROGRESS) &&
-           wcb.error() != Err(Errno::EINPROGRESS) {
+        if rcb.error() != Err(Error::from(Errno::EINPROGRESS)) &&
+           wcb.error() != Err(Error::from(Errno::EINPROGRESS)) {
             break
         }
     }
@@ -343,6 +335,61 @@
     assert_eq!(rbuf, EXPECT);
 }
 
+// Tests `AioCb::from_boxed_slice` with `Bytes`
+#[test]
+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
+fn test_write_bytes() {
+    const INITIAL: &[u8] = b"abcdef123456";
+    let wbuf = Box::new(Bytes::from(&b"CDEF"[..]));
+    let mut rbuf = Vec::new();
+    const EXPECT: &[u8] = b"abCDEF123456";
+    let expected_len = wbuf.len();
+
+    let mut f = tempfile().unwrap();
+    f.write_all(INITIAL).unwrap();
+    let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
+                           2,   //offset
+                           wbuf,
+                           0,   //priority
+                           SigevNotify::SigevNone,
+                           LioOpcode::LIO_NOP);
+    aiocb.write().unwrap();
+
+    let err = poll_aio(&mut aiocb);
+    assert_eq!(err, Ok(()));
+    assert_eq!(aiocb.aio_return().unwrap() as usize, expected_len);
+
+    f.seek(SeekFrom::Start(0)).unwrap();
+    let len = f.read_to_end(&mut rbuf).unwrap();
+    assert_eq!(len, EXPECT.len());
+    assert_eq!(rbuf, EXPECT);
+}
+
+// Tests `AioCb::from_boxed_mut_slice` with `BytesMut`
+#[test]
+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
+fn test_read_bytes_mut_small() {
+    const INITIAL: &[u8] = b"abcdef";
+    let rbuf = Box::new(BytesMut::from(vec![0; 4]));
+    const EXPECT: &[u8] = b"cdef";
+    let mut f = tempfile().unwrap();
+    f.write_all(INITIAL).unwrap();
+
+    let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
+                           2,   //offset
+                           rbuf,
+                           0,   //priority
+                           SigevNotify::SigevNone,
+                           LioOpcode::LIO_NOP);
+    aiocb.read().unwrap();
+
+    let err = poll_aio(&mut aiocb);
+    assert_eq!(err, Ok(()));
+    assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
+    let buffer = aiocb.boxed_mut_slice().unwrap();
+    assert_eq!(buffer.borrow(), EXPECT);
+}
+
 // Tests `AioCb::from_ptr`
 #[test]
 #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
@@ -406,7 +453,7 @@
 #[test]
 #[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips", target_arch = "mips64"), ignore)]
 fn test_write_sigev_signal() {
-    let _m = crate::SIGNAL_MTX.lock();
+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
     let sa = SigAction::new(SigHandler::Handler(sigfunc),
                             SaFlags::SA_RESETHAND,
                             SigSet::empty());
@@ -458,22 +505,22 @@
     f.write_all(INITIAL).unwrap();
 
     {
-        let mut liocb = LioCbBuilder::with_capacity(2)
-            .emplace_slice(
-                f.as_raw_fd(),
-                2,   //offset
-                WBUF,
-                0,   //priority
-                SigevNotify::SigevNone,
-                LioOpcode::LIO_WRITE
-            ).emplace_mut_slice(
-                f.as_raw_fd(),
-                8,   //offset
-                &mut rbuf,
-                0,   //priority
-                SigevNotify::SigevNone,
-                LioOpcode::LIO_READ
-            ).finish();
+        let wcb = AioCb::from_slice( f.as_raw_fd(),
+                               2,   //offset
+                               WBUF,
+                               0,   //priority
+                               SigevNotify::SigevNone,
+                               LioOpcode::LIO_WRITE);
+
+        let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
+                                8,   //offset
+                                &mut rbuf,
+                                0,   //priority
+                                SigevNotify::SigevNone,
+                                LioOpcode::LIO_READ);
+        let mut liocb = LioCb::with_capacity(2);
+        liocb.aiocbs.push(wcb);
+        liocb.aiocbs.push(rcb);
         let err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
         err.expect("lio_listio");
 
@@ -505,29 +552,29 @@
     f.write_all(INITIAL).unwrap();
 
     {
-        let mut liocb = LioCbBuilder::with_capacity(2)
-            .emplace_slice(
-                f.as_raw_fd(),
-                2,   //offset
-                WBUF,
-                0,   //priority
-                SigevNotify::SigevNone,
-                LioOpcode::LIO_WRITE
-            ).emplace_mut_slice(
-                f.as_raw_fd(),
-                8,   //offset
-                &mut rbuf,
-                0,   //priority
-                SigevNotify::SigevNone,
-                LioOpcode::LIO_READ
-            ).finish();
+        let wcb = AioCb::from_slice( f.as_raw_fd(),
+                               2,   //offset
+                               WBUF,
+                               0,   //priority
+                               SigevNotify::SigevNone,
+                               LioOpcode::LIO_WRITE);
+
+        let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
+                                8,   //offset
+                                &mut rbuf,
+                                0,   //priority
+                                SigevNotify::SigevNone,
+                                LioOpcode::LIO_READ);
+        let mut liocb = LioCb::with_capacity(2);
+        liocb.aiocbs.push(wcb);
+        liocb.aiocbs.push(rcb);
         let err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
         err.expect("lio_listio");
 
-        poll_lio(&mut liocb, 0).unwrap();
-        poll_lio(&mut liocb, 1).unwrap();
-        assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
-        assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen);
+        poll_aio(&mut liocb.aiocbs[0]).unwrap();
+        poll_aio(&mut liocb.aiocbs[1]).unwrap();
+        assert_eq!(liocb.aiocbs[0].aio_return().unwrap() as usize, WBUF.len());
+        assert_eq!(liocb.aiocbs[1].aio_return().unwrap() as usize, rlen);
     }
     assert_eq!(rbuf.deref().deref(), b"3456");
 
@@ -544,7 +591,7 @@
 #[cfg(not(any(target_os = "ios", target_os = "macos")))]
 #[cfg_attr(any(target_arch = "mips", target_arch = "mips64", target_env = "musl"), ignore)]
 fn test_liocb_listio_signal() {
-    let _m = crate::SIGNAL_MTX.lock();
+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
     const INITIAL: &[u8] = b"abcdef123456";
     const WBUF: &[u8] = b"CDEF";
     let mut rbuf = vec![0; 4];
@@ -561,22 +608,22 @@
     f.write_all(INITIAL).unwrap();
 
     {
-        let mut liocb = LioCbBuilder::with_capacity(2)
-            .emplace_slice(
-                f.as_raw_fd(),
-                2,   //offset
-                WBUF,
-                0,   //priority
-                SigevNotify::SigevNone,
-                LioOpcode::LIO_WRITE
-            ).emplace_mut_slice(
-                f.as_raw_fd(),
-                8,   //offset
-                &mut rbuf,
-                0,   //priority
-                SigevNotify::SigevNone,
-                LioOpcode::LIO_READ
-            ).finish();
+        let wcb = AioCb::from_slice( f.as_raw_fd(),
+                               2,   //offset
+                               WBUF,
+                               0,   //priority
+                               SigevNotify::SigevNone,
+                               LioOpcode::LIO_WRITE);
+
+        let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
+                                8,   //offset
+                                &mut rbuf,
+                                0,   //priority
+                                SigevNotify::SigevNone,
+                                LioOpcode::LIO_READ);
+        let mut liocb = LioCb::with_capacity(2);
+        liocb.aiocbs.push(wcb);
+        liocb.aiocbs.push(rcb);
         SIGNALED.store(false, Ordering::Relaxed);
         unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
         let err = liocb.listio(LioMode::LIO_NOWAIT, sigev_notify);
@@ -585,8 +632,8 @@
             thread::sleep(time::Duration::from_millis(10));
         }
 
-        assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
-        assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen);
+        assert_eq!(liocb.aiocbs[0].aio_return().unwrap() as usize, WBUF.len());
+        assert_eq!(liocb.aiocbs[1].aio_return().unwrap() as usize, rlen);
     }
     assert_eq!(rbuf.deref().deref(), b"3456");
 
@@ -607,14 +654,13 @@
     let f = tempfile().unwrap();
 
 
-    let mut liocb = LioCbBuilder::with_capacity(1)
-        .emplace_slice(
-            f.as_raw_fd(),
+    let mut liocb = LioCb::from(vec![
+        AioCb::from_slice( f.as_raw_fd(),
             2,   //offset
             rbuf,
             0,   //priority
             SigevNotify::SigevNone,
-            LioOpcode::LIO_READ
-        ).finish();
+            LioOpcode::LIO_READ)
+    ]);
     let _ = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
 }
diff --git a/test/sys/test_aio_drop.rs b/test/sys/test_aio_drop.rs
index 71a2183..784ee3e 100644
--- a/test/sys/test_aio_drop.rs
+++ b/test/sys/test_aio_drop.rs
@@ -9,6 +9,7 @@
               target_os = "macos",
               target_os = "freebsd",
               target_os = "netbsd")))]
+#[cfg_attr(target_env = "gnu", ignore = "Occasionally fails in Travis; glibc bug suspected")]
 fn test_drop() {
     use nix::sys::aio::*;
     use nix::sys::signal::*;
diff --git a/test/sys/test_epoll.rs b/test/sys/test_epoll.rs
index 8d44cd0..e0dc513 100644
--- a/test/sys/test_epoll.rs
+++ b/test/sys/test_epoll.rs
@@ -1,5 +1,6 @@
 use nix::sys::epoll::{EpollCreateFlags, EpollFlags, EpollOp, EpollEvent};
 use nix::sys::epoll::{epoll_create1, epoll_ctl};
+use nix::Error;
 use nix::errno::Errno;
 
 #[test]
@@ -7,11 +8,11 @@
     let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
     let result = epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None);
     assert!(result.is_err());
-    assert_eq!(result.unwrap_err(), Errno::ENOENT);
+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::ENOENT));
 
     let result = epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, None);
     assert!(result.is_err());
-    assert_eq!(result.unwrap_err(), Errno::EINVAL);
+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::EINVAL));
 }
 
 #[test]
diff --git a/test/sys/test_inotify.rs b/test/sys/test_inotify.rs
index 137816a..a8ead46 100644
--- a/test/sys/test_inotify.rs
+++ b/test/sys/test_inotify.rs
@@ -1,5 +1,7 @@
 use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify};
+use nix::Error;
 use nix::errno::Errno;
+use tempfile;
 use std::ffi::OsString;
 use std::fs::{rename, File};
 
@@ -12,7 +14,7 @@
     instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
 
     let events = instance.read_events();
-    assert_eq!(events.unwrap_err(), Errno::EAGAIN);
+    assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));
 
     File::create(tempdir.path().join("test")).unwrap();
 
@@ -29,7 +31,7 @@
     instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
 
     let events = instance.read_events();
-    assert_eq!(events.unwrap_err(), Errno::EAGAIN);
+    assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));
 
     File::create(tempdir.path().join("test")).unwrap();
     rename(tempdir.path().join("test"), tempdir.path().join("test2")).unwrap();
diff --git a/test/sys/test_ioctl.rs b/test/sys/test_ioctl.rs
index 236d242..fa4510a 100644
--- a/test/sys/test_ioctl.rs
+++ b/test/sys/test_ioctl.rs
@@ -56,10 +56,10 @@
     #[test]
     fn test_op_write_64() {
         if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
-            assert_eq!(request_code_write!(b'z', 10, 1u64 << 32) as u32,
+            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32) as u32,
                        0x8000_7A0A);
         } else {
-            assert_eq!(request_code_write!(b'z', 10, 1u64 << 32) as u32,
+            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32) as u32,
                        0x4000_7A0A);
         }
 
@@ -80,10 +80,10 @@
     #[test]
     fn test_op_read_64() {
         if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
-            assert_eq!(request_code_read!(b'z', 10, 1u64 << 32) as u32,
+            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32) as u32,
                        0x4000_7A0A);
         } else {
-            assert_eq!(request_code_read!(b'z', 10, 1u64 << 32) as u32,
+            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32) as u32,
                        0x8000_7A0A);
         }
     }
@@ -97,7 +97,7 @@
     #[cfg(target_pointer_width = "64")]
     #[test]
     fn test_op_read_write_64() {
-        assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32) as u32,
+        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32) as u32,
                    0xC000_7A0A);
     }
 }
@@ -131,7 +131,7 @@
     #[cfg(target_pointer_width = "64")]
     #[test]
     fn test_op_write_64() {
-        assert_eq!(request_code_write!(b'z', 10, 1u64 << 32), 0x8000_7A0A);
+        assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
     }
 
     #[test]
@@ -143,7 +143,7 @@
     #[cfg(target_pointer_width = "64")]
     #[test]
     fn test_op_read_64() {
-        assert_eq!(request_code_read!(b'z', 10, 1u64 << 32), 0x4000_7A0A);
+        assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
     }
 
     #[test]
@@ -155,7 +155,7 @@
     #[cfg(target_pointer_width = "64")]
     #[test]
     fn test_op_read_write_64() {
-        assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32), 0xC000_7A0A);
+        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32), 0xC000_7A0A);
     }
 }
 
@@ -167,14 +167,15 @@
     use tempfile::tempfile;
     use libc::{TCGETS, TCSBRK, TCSETS, TIOCNXCL, termios};
 
-    use nix::errno::Errno;
+    use nix::Error::Sys;
+    use nix::errno::Errno::{ENOTTY, ENOSYS};
 
     ioctl_none_bad!(tiocnxcl, TIOCNXCL);
     #[test]
     fn test_ioctl_none_bad() {
         let file = tempfile().unwrap();
         let res = unsafe { tiocnxcl(file.as_raw_fd()) };
-        assert_eq!(res, Err(Errno::ENOTTY));
+        assert_eq!(res, Err(Sys(ENOTTY)));
     }
 
     ioctl_read_bad!(tcgets, TCGETS, termios);
@@ -183,7 +184,7 @@
         let file = tempfile().unwrap();
         let mut termios = unsafe { mem::zeroed() };
         let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) };
-        assert_eq!(res, Err(Errno::ENOTTY));
+        assert_eq!(res, Err(Sys(ENOTTY)));
     }
 
     ioctl_write_int_bad!(tcsbrk, TCSBRK);
@@ -191,7 +192,7 @@
     fn test_ioctl_write_int_bad() {
         let file = tempfile().unwrap();
         let res = unsafe { tcsbrk(file.as_raw_fd(), 0) };
-        assert_eq!(res, Err(Errno::ENOTTY));
+        assert_eq!(res, Err(Sys(ENOTTY)));
     }
 
     ioctl_write_ptr_bad!(tcsets, TCSETS, termios);
@@ -200,7 +201,7 @@
         let file = tempfile().unwrap();
         let termios: termios = unsafe { mem::zeroed() };
         let res = unsafe { tcsets(file.as_raw_fd(), &termios) };
-        assert_eq!(res, Err(Errno::ENOTTY));
+        assert_eq!(res, Err(Sys(ENOTTY)));
     }
 
     // FIXME: Find a suitable example for `ioctl_readwrite_bad`
@@ -211,7 +212,7 @@
     fn test_ioctl_none() {
         let file = tempfile().unwrap();
         let res = unsafe { log_status(file.as_raw_fd()) };
-        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
     }
 
     #[repr(C)]
@@ -230,7 +231,7 @@
         let file = tempfile().unwrap();
         let data: v4l2_audio = unsafe { mem::zeroed() };
         let res = unsafe { s_audio(file.as_raw_fd(), &data) };
-        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
     }
 
     // From linux/net/bluetooth/hci_sock.h
@@ -241,7 +242,7 @@
     fn test_ioctl_write_int() {
         let file = tempfile().unwrap();
         let res = unsafe { hcidevup(file.as_raw_fd(), 0) };
-        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
     }
 
     // From linux/videodev2.h
@@ -251,7 +252,7 @@
         let file = tempfile().unwrap();
         let mut data: v4l2_audio = unsafe { mem::zeroed() };
         let res = unsafe { g_audio(file.as_raw_fd(), &mut data) };
-        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
     }
 
     // From linux/videodev2.h
@@ -261,7 +262,7 @@
         let file = tempfile().unwrap();
         let mut data: v4l2_audio = unsafe { mem::zeroed() };
         let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) };
-        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
     }
 
     // FIXME: Find a suitable example for `ioctl_read_buf`.
@@ -287,7 +288,7 @@
         let file = tempfile().unwrap();
         let data: [spi_ioc_transfer; 4] = unsafe { mem::zeroed() };
         let res = unsafe { spi_ioc_message(file.as_raw_fd(), &data[..]) };
-        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
     }
 
     // FIXME: Find a suitable example for `ioctl_readwrite_buf`.
@@ -301,7 +302,8 @@
     use tempfile::tempfile;
     use libc::termios;
 
-    use nix::errno::Errno;
+    use nix::Error::Sys;
+    use nix::errno::Errno::ENOTTY;
 
     // From sys/sys/ttycom.h
     const TTY_IOC_MAGIC: u8 = b't';
@@ -314,7 +316,7 @@
     fn test_ioctl_none() {
         let file = tempfile().unwrap();
         let res = unsafe { tiocnxcl(file.as_raw_fd()) };
-        assert_eq!(res, Err(Errno::ENOTTY));
+        assert_eq!(res, Err(Sys(ENOTTY)));
     }
 
     ioctl_read!(tiocgeta, TTY_IOC_MAGIC, TTY_IOC_TYPE_GETA, termios);
@@ -323,7 +325,7 @@
         let file = tempfile().unwrap();
         let mut termios = unsafe { mem::zeroed() };
         let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) };
-        assert_eq!(res, Err(Errno::ENOTTY));
+        assert_eq!(res, Err(Sys(ENOTTY)));
     }
 
     ioctl_write_ptr!(tiocseta, TTY_IOC_MAGIC, TTY_IOC_TYPE_SETA, termios);
@@ -332,6 +334,6 @@
         let file = tempfile().unwrap();
         let termios: termios = unsafe { mem::zeroed() };
         let res = unsafe { tiocseta(file.as_raw_fd(), &termios) };
-        assert_eq!(res, Err(Errno::ENOTTY));
+        assert_eq!(res, Err(Sys(ENOTTY)));
     }
 }
diff --git a/test/sys/test_lio_listio_resubmit.rs b/test/sys/test_lio_listio_resubmit.rs
index c907789..0795370 100644
--- a/test/sys/test_lio_listio_resubmit.rs
+++ b/test/sys/test_lio_listio_resubmit.rs
@@ -4,6 +4,7 @@
 // we must disable the test here rather than in Cargo.toml
 #![cfg(target_os = "freebsd")]
 
+use nix::Error;
 use nix::errno::*;
 use nix::libc::off_t;
 use nix::sys::aio::*;
@@ -19,12 +20,12 @@
 /// Attempt to collect final status for all of `liocb`'s operations, freeing
 /// system resources
 fn finish_liocb(liocb: &mut LioCb) {
-    for j in 0..liocb.len() {
+    for j in 0..liocb.aiocbs.len() {
         loop {
             let e = liocb.error(j);
             match e {
                 Ok(()) => break,
-                Err(Errno::EINPROGRESS) =>
+                Err(Error::Sys(Errno::EINPROGRESS)) =>
                     thread::sleep(time::Duration::from_millis(10)),
                 Err(x) => panic!("aio_error({:?})", x)
             }
@@ -69,21 +70,21 @@
     }).collect::<Vec<_>>();
 
     let mut liocbs = (0..num_listios).map(|i| {
-        let mut builder = LioCbBuilder::with_capacity(ops_per_listio);
+        let mut liocb = LioCb::with_capacity(ops_per_listio);
         for j in 0..ops_per_listio {
             let offset = (BYTES_PER_OP * (i * ops_per_listio + j)) as off_t;
-            builder = builder.emplace_slice(f.as_raw_fd(),
-                                offset,
-                                &buffer_set[i][j][..],
-                                0,   //priority
-                                SigevNotify::SigevNone,
-                                LioOpcode::LIO_WRITE);
+            let wcb = AioCb::from_slice( f.as_raw_fd(),
+                                   offset,
+                                   &buffer_set[i][j][..],
+                                   0,   //priority
+                                   SigevNotify::SigevNone,
+                                   LioOpcode::LIO_WRITE);
+            liocb.aiocbs.push(wcb);
         }
-        let mut liocb = builder.finish();
         let mut err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
-        while err == Err(Errno::EIO) ||
-              err == Err(Errno::EAGAIN) ||
-              err == Err(Errno::EINTR) {
+        while err == Err(Error::Sys(Errno::EIO)) ||
+              err == Err(Error::Sys(Errno::EAGAIN)) ||
+              err == Err(Error::Sys(Errno::EINTR)) {
             // 
             thread::sleep(time::Duration::from_millis(10));
             resubmit_count += 1;
diff --git a/test/sys/test_mman.rs b/test/sys/test_mman.rs
index a7ceedc..152fff6 100644
--- a/test/sys/test_mman.rs
+++ b/test/sys/test_mman.rs
@@ -1,24 +1,27 @@
+use nix::Error;
+use nix::libc::{c_void, size_t};
 use nix::sys::mman::{mmap, MapFlags, ProtFlags};
 
+#[cfg(target_os = "linux")]
+use nix::sys::mman::{mremap, MRemapFlags};
+
 #[test]
 fn test_mmap_anonymous() {
-    unsafe {
+    let ref mut byte = unsafe {
         let ptr = mmap(std::ptr::null_mut(), 1,
                        ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
                        MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS, -1, 0)
-                      .unwrap() as *mut u8;
-        assert_eq !(*ptr, 0x00u8);
-        *ptr = 0xffu8;
-        assert_eq !(*ptr, 0xffu8);
-    }
+                      .unwrap();
+        *(ptr as * mut u8)
+    };
+    assert_eq !(*byte, 0x00u8);
+    *byte = 0xffu8;
+    assert_eq !(*byte, 0xffu8);
 }
 
 #[test]
-#[cfg(any(target_os = "linux", target_os = "netbsd"))]
+#[cfg(target_os = "linux")]
 fn test_mremap_grow() {
-    use nix::sys::mman::{mremap, MRemapFlags};
-    use nix::libc::{c_void, size_t};
-
     const ONE_K : size_t = 1024;
     let slice : &mut[u8] = unsafe {
         let mem = mmap(std::ptr::null_mut(), ONE_K,
@@ -32,14 +35,9 @@
     assert_eq !(slice[ONE_K - 1], 0xFF);
 
     let slice : &mut[u8] = unsafe {
-        #[cfg(target_os = "linux")]
         let mem = mremap(slice.as_mut_ptr() as * mut c_void, ONE_K, 10 * ONE_K,
                          MRemapFlags::MREMAP_MAYMOVE, None)
                       .unwrap();
-        #[cfg(target_os = "netbsd")]
-        let mem = mremap(slice.as_mut_ptr() as * mut c_void, ONE_K, 10 * ONE_K,
-                         MRemapFlags::MAP_REMAPDUP, None)
-                      .unwrap();
         std::slice::from_raw_parts_mut(mem as * mut u8, 10 * ONE_K)
     };
 
@@ -53,13 +51,8 @@
 }
 
 #[test]
-#[cfg(any(target_os = "linux", target_os = "netbsd"))]
-// Segfaults for unknown reasons under QEMU for 32-bit targets
-#[cfg_attr(all(target_pointer_width = "32", qemu), ignore)]
+#[cfg(target_os = "linux")]
 fn test_mremap_shrink() {
-    use nix::sys::mman::{mremap, MRemapFlags};
-    use nix::libc::{c_void, size_t};
-
     const ONE_K : size_t = 1024;
     let slice : &mut[u8] = unsafe {
         let mem = mmap(std::ptr::null_mut(), 10 * ONE_K,
@@ -73,16 +66,11 @@
     assert_eq !(slice[ONE_K - 1], 0xFF);
 
     let slice : &mut[u8] = unsafe {
-        #[cfg(target_os = "linux")]
         let mem = mremap(slice.as_mut_ptr() as * mut c_void, 10 * ONE_K, ONE_K,
                          MRemapFlags::empty(), None)
                       .unwrap();
         // Since we didn't supply MREMAP_MAYMOVE, the address should be the
         // same.
-        #[cfg(target_os = "netbsd")]
-        let mem = mremap(slice.as_mut_ptr() as * mut c_void, 10 * ONE_K, ONE_K,
-                         MRemapFlags::MAP_FIXED, None)
-                      .unwrap();
         assert_eq !(mem, slice.as_mut_ptr() as * mut c_void);
         std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
     };
diff --git a/test/sys/test_pthread.rs b/test/sys/test_pthread.rs
index fa9b510..1fc3dd9 100644
--- a/test/sys/test_pthread.rs
+++ b/test/sys/test_pthread.rs
@@ -13,10 +13,3 @@
     let tid = pthread_self();
     assert!(tid != 0);
 }
-
-#[test]
-#[cfg(not(target_os = "redox"))]
-fn test_pthread_kill_none() {
-    pthread_kill(pthread_self(), None)
-        .expect("Should be able to send signal to my thread.");
-}
diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs
index 83fff9a..b9793b3 100644
--- a/test/sys/test_ptrace.rs
+++ b/test/sys/test_ptrace.rs
@@ -1,3 +1,4 @@
+use nix::Error;
 use nix::errno::Errno;
 use nix::unistd::getpid;
 use nix::sys::ptrace;
@@ -13,37 +14,37 @@
 fn test_ptrace() {
     // Just make sure ptrace can be called at all, for now.
     // FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS
-    require_capability!("test_ptrace", CAP_SYS_PTRACE);
+    require_capability!(CAP_SYS_PTRACE);
     let err = ptrace::attach(getpid()).unwrap_err();
-    assert!(err == Errno::EPERM || err == Errno::EINVAL ||
-            err == Errno::ENOSYS);
+    assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::EINVAL) ||
+            err == Error::Sys(Errno::ENOSYS));
 }
 
 // Just make sure ptrace_setoptions can be called at all, for now.
 #[test]
 #[cfg(any(target_os = "android", target_os = "linux"))]
 fn test_ptrace_setoptions() {
-    require_capability!("test_ptrace_setoptions", CAP_SYS_PTRACE);
+    require_capability!(CAP_SYS_PTRACE);
     let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
-    assert!(err != Errno::EOPNOTSUPP);
+    assert!(err != Error::UnsupportedOperation);
 }
 
 // Just make sure ptrace_getevent can be called at all, for now.
 #[test]
 #[cfg(any(target_os = "android", target_os = "linux"))]
 fn test_ptrace_getevent() {
-    require_capability!("test_ptrace_getevent", CAP_SYS_PTRACE);
+    require_capability!(CAP_SYS_PTRACE);
     let err = ptrace::getevent(getpid()).unwrap_err();
-    assert!(err != Errno::EOPNOTSUPP);
+    assert!(err != Error::UnsupportedOperation);
 }
 
 // Just make sure ptrace_getsiginfo can be called at all, for now.
 #[test]
 #[cfg(any(target_os = "android", target_os = "linux"))]
 fn test_ptrace_getsiginfo() {
-    require_capability!("test_ptrace_getsiginfo", CAP_SYS_PTRACE);
-    if let Err(Errno::EOPNOTSUPP) = ptrace::getsiginfo(getpid()) {
-        panic!("ptrace_getsiginfo returns Errno::EOPNOTSUPP!");
+    require_capability!(CAP_SYS_PTRACE);
+    if let Err(Error::UnsupportedOperation) = ptrace::getsiginfo(getpid()) {
+        panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!");
     }
 }
 
@@ -51,10 +52,10 @@
 #[test]
 #[cfg(any(target_os = "android", target_os = "linux"))]
 fn test_ptrace_setsiginfo() {
-    require_capability!("test_ptrace_setsiginfo", CAP_SYS_PTRACE);
+    require_capability!(CAP_SYS_PTRACE);
     let siginfo = unsafe { mem::zeroed() };
-    if let Err(Errno::EOPNOTSUPP) = ptrace::setsiginfo(getpid(), &siginfo) {
-        panic!("ptrace_setsiginfo returns Errno::EOPNOTSUPP!");
+    if let Err(Error::UnsupportedOperation) = ptrace::setsiginfo(getpid(), &siginfo) {
+        panic!("ptrace_setsiginfo returns Error::UnsupportedOperation!");
     }
 }
 
@@ -67,9 +68,9 @@
     use nix::unistd::fork;
     use nix::unistd::ForkResult::*;
 
-    require_capability!("test_ptrace_cont", CAP_SYS_PTRACE);
+    require_capability!(CAP_SYS_PTRACE);
 
-    let _m = crate::FORK_MTX.lock();
+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
     // FIXME: qemu-user doesn't implement ptrace on all architectures
     // and retunrs ENOSYS in this case.
@@ -78,7 +79,7 @@
     // On valid platforms the ptrace call should return Errno::EPERM, this
     // is already tested by `test_ptrace`.
     let err = ptrace::attach(getpid()).unwrap_err();
-    if err == Errno::ENOSYS {
+    if err == Error::Sys(Errno::ENOSYS) {
         return;
     }
 
@@ -114,48 +115,6 @@
     }
 }
 
-#[cfg(target_os = "linux")]
-#[test]
-fn test_ptrace_interrupt() {
-    use nix::sys::ptrace;
-    use nix::sys::signal::Signal;
-    use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
-    use nix::unistd::fork;
-    use nix::unistd::ForkResult::*;
-    use std::thread::sleep;
-    use std::time::Duration;
-
-    require_capability!("test_ptrace_interrupt", CAP_SYS_PTRACE);
-
-    let _m = crate::FORK_MTX.lock();
-
-    match unsafe{fork()}.expect("Error: Fork Failed") {
-        Child => {
-            loop {
-                sleep(Duration::from_millis(1000));
-            }
-
-        },
-        Parent { child } => {
-            ptrace::seize(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap();
-            ptrace::interrupt(child).unwrap();
-            assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, Signal::SIGTRAP, 128)));
-            ptrace::syscall(child, None).unwrap();
-            assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
-            ptrace::detach(child, Some(Signal::SIGKILL)).unwrap();
-            match waitpid(child, None) {
-                Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
-                    let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
-                    while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() {
-                        let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
-                    }
-                }
-                _ => panic!("The process should have been killed"),
-            }
-        },
-    }
-}
-
 // ptrace::{setoptions, getregs} are only available in these platforms
 #[cfg(all(target_os = "linux",
           any(target_arch = "x86_64",
@@ -171,9 +130,9 @@
     use nix::unistd::getpid;
     use nix::unistd::ForkResult::*;
 
-    require_capability!("test_ptrace_syscall", CAP_SYS_PTRACE);
+    require_capability!(CAP_SYS_PTRACE);
 
-    let _m = crate::FORK_MTX.lock();
+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
     match unsafe{fork()}.expect("Error: Fork Failed") {
         Child => {
diff --git a/test/sys/test_select.rs b/test/sys/test_select.rs
index 2f7396b..3795108 100644
--- a/test/sys/test_select.rs
+++ b/test/sys/test_select.rs
@@ -5,7 +5,9 @@
 
 #[test]
 pub fn test_pselect() {
-    let _mtx = crate::SIGNAL_MTX.lock();
+    let _mtx = crate::SIGNAL_MTX
+        .lock()
+        .expect("Mutex got poisoned by another test");
 
     let (r1, w1) = pipe().unwrap();
     write(w1, b"hi!").unwrap();
@@ -50,31 +52,3 @@
     assert!(fd_set.contains(r1));
     assert!(!fd_set.contains(r2));
 }
-
-macro_rules! generate_fdset_bad_fd_tests {
-    ($fd:expr, $($method:ident),* $(,)?) => {
-        $(
-            #[test]
-            #[should_panic]
-            fn $method() {
-                FdSet::new().$method($fd);
-            }
-        )*
-    }
-}
-
-mod test_fdset_negative_fd {
-    use super::*;
-    generate_fdset_bad_fd_tests!(-1, insert, remove, contains);
-}
-
-mod test_fdset_too_large_fd {
-    use super::*;
-    use std::convert::TryInto;
-    generate_fdset_bad_fd_tests!(
-        FD_SETSIZE.try_into().unwrap(),
-        insert,
-        remove,
-        contains,
-    );
-}
diff --git a/test/sys/test_signal.rs b/test/sys/test_signal.rs
index fdd2568..ae22527 100644
--- a/test/sys/test_signal.rs
+++ b/test/sys/test_signal.rs
@@ -1,5 +1,6 @@
+use libc;
 #[cfg(not(target_os = "redox"))]
-use nix::errno::Errno;
+use nix::Error;
 use nix::sys::signal::*;
 use nix::unistd::*;
 use std::convert::TryFrom;
@@ -19,7 +20,7 @@
 
 #[test]
 fn test_old_sigaction_flags() {
-    let _m = crate::SIGNAL_MTX.lock();
+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
 
     extern "C" fn handler(_: ::libc::c_int) {}
     let act = SigAction::new(
@@ -41,7 +42,7 @@
 
 #[test]
 fn test_sigprocmask() {
-    let _m = crate::SIGNAL_MTX.lock();
+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
 
     // This needs to be a signal that rust doesn't use in the test harness.
     const SIGNAL: Signal = Signal::SIGCHLD;
@@ -52,9 +53,9 @@
 
     // Make sure the old set doesn't contain the signal, otherwise the following
     // test don't make sense.
-    assert!(!old_signal_set.contains(SIGNAL),
-            "the {:?} signal is already blocked, please change to a \
-             different one", SIGNAL);
+    assert_eq!(old_signal_set.contains(SIGNAL), false,
+               "the {:?} signal is already blocked, please change to a \
+                different one", SIGNAL);
 
     // Now block the signal.
     let mut signal_set = SigSet::empty();
@@ -66,8 +67,8 @@
     old_signal_set.clear();
     sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
         .expect("expect to be able to retrieve old signals");
-    assert!(old_signal_set.contains(SIGNAL),
-            "expected the {:?} to be blocked", SIGNAL);
+    assert_eq!(old_signal_set.contains(SIGNAL), true,
+               "expected the {:?} to be blocked", SIGNAL);
 
     // Reset the signal.
     sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&signal_set), None)
@@ -89,15 +90,15 @@
 #[test]
 #[cfg(not(target_os = "redox"))]
 fn test_signal_sigaction() {
-    let _m = crate::SIGNAL_MTX.lock();
+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
 
     let action_handler = SigHandler::SigAction(test_sigaction_action);
-    assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Errno::ENOTSUP);
+    assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Error::UnsupportedOperation);
 }
 
 #[test]
 fn test_signal() {
-    let _m = crate::SIGNAL_MTX.lock();
+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
 
     unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
     raise(Signal::SIGINT).unwrap();
@@ -107,15 +108,8 @@
     assert_eq!(unsafe { signal(Signal::SIGINT, handler) }.unwrap(), SigHandler::SigDfl);
     raise(Signal::SIGINT).unwrap();
     assert!(SIGNALED.load(Ordering::Relaxed));
-
-    #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
     assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), handler);
 
-    // System V based OSes (e.g. illumos and Solaris) always resets the
-    // disposition to SIG_DFL prior to calling the signal handler
-    #[cfg(any(target_os = "illumos", target_os = "solaris"))]
-    assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), SigHandler::SigDfl);
-
     // Restore default signal handler
     unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap();
 }
diff --git a/test/sys/test_signalfd.rs b/test/sys/test_signalfd.rs
index b6f748b..af04c22 100644
--- a/test/sys/test_signalfd.rs
+++ b/test/sys/test_signalfd.rs
@@ -6,7 +6,7 @@
     use nix::sys::signal::{self, raise, Signal, SigSet};
 
     // Grab the mutex for altering signals so we don't interfere with other tests.
-    let _m = crate::SIGNAL_MTX.lock();
+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Block the SIGUSR1 signal from automatic processing for this thread
     let mut mask = SigSet::empty();
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index 0f6fac6..7eab28c 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -1,13 +1,13 @@
-use nix::sys::socket::{AddressFamily, InetAddr, SockAddr, UnixAddr, getsockname, sockaddr, sockaddr_in6, sockaddr_storage_to_addr};
+use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname};
 use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
-use std::mem::{self, MaybeUninit};
 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 libc::{c_char, sockaddr_storage};
+use libc::c_char;
+use tempfile;
 #[cfg(any(target_os = "linux", target_os= "android"))]
 use crate::*;
 
@@ -28,36 +28,13 @@
         _ => panic!("nope"),
     }
 
-    assert_eq!(addr.to_string(), "127.0.0.1:3000");
+    assert_eq!(addr.to_str(), "127.0.0.1:3000");
 
     let inet = addr.to_std();
     assert_eq!(actual, inet);
 }
 
 #[test]
-pub fn test_inetv4_addr_roundtrip_sockaddr_storage_to_addr() {
-    let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
-    let addr = InetAddr::from_std(&actual);
-    let sockaddr = SockAddr::new_inet(addr);
-
-    let (storage, ffi_size) = {
-        let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
-        let storage_ptr = storage.as_mut_ptr().cast::<sockaddr>();
-        let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
-        assert_eq!(mem::size_of::<sockaddr>(), ffi_size as usize);
-        unsafe {
-            storage_ptr.copy_from_nonoverlapping(ffi_ptr as *const sockaddr, 1);
-            (storage.assume_init(), ffi_size)
-        }
-    };
-
-    let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
-    assert_eq!(from_storage, sockaddr);
-    let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap();
-    assert_eq!(from_storage, sockaddr);
-}
-
-#[test]
 pub fn test_inetv6_addr_to_sock_addr() {
     let port: u16 = 3000;
     let flowinfo: u32 = 1;
@@ -78,33 +55,6 @@
 
     assert_eq!(actual, addr.to_std());
 }
-#[test]
-pub fn test_inetv6_addr_roundtrip_sockaddr_storage_to_addr() {
-    let port: u16 = 3000;
-    let flowinfo: u32 = 1;
-    let scope_id: u32 = 2;
-    let ip: Ipv6Addr = "fe80::1".parse().unwrap();
-
-    let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
-    let addr = InetAddr::from_std(&actual);
-    let sockaddr = SockAddr::new_inet(addr);
-
-    let (storage, ffi_size) = {
-        let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
-        let storage_ptr = storage.as_mut_ptr().cast::<sockaddr_in6>();
-        let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
-        assert_eq!(mem::size_of::<sockaddr_in6>(), ffi_size as usize);
-        unsafe {
-            storage_ptr.copy_from_nonoverlapping((ffi_ptr as *const sockaddr).cast::<sockaddr_in6>(), 1);
-            (storage.assume_init(), ffi_size)
-        }
-    };
-
-    let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
-    assert_eq!(from_storage, sockaddr);
-    let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()).unwrap();
-    assert_eq!(from_storage, sockaddr);
-}
 
 #[test]
 pub fn test_path_to_sock_addr() {
@@ -113,9 +63,9 @@
     let addr = UnixAddr::new(actual).unwrap();
 
     let expect: &[c_char] = unsafe {
-        slice::from_raw_parts(path.as_ptr() as *const c_char, path.len())
+        slice::from_raw_parts(path.as_bytes().as_ptr() as *const c_char, path.len())
     };
-    assert_eq!(unsafe { &(*addr.as_ptr()).sun_path[..8] }, expect);
+    assert_eq!(&addr.0.sun_path[..8], expect);
 
     assert_eq!(addr.path(), Some(actual));
 }
@@ -131,9 +81,9 @@
     let path = "/foo/bar";
     let actual = Path::new(path);
     let addr1 = UnixAddr::new(actual).unwrap();
-    let mut addr2 = addr1;
+    let mut addr2 = addr1.clone();
 
-    unsafe { (*addr2.as_mut_ptr()).sun_path[10] = 127 };
+    addr2.0.sun_path[10] = 127;
 
     assert_eq!(addr1, addr2);
     assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
@@ -152,12 +102,12 @@
 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;
+    let mut addr2 = addr1.clone();
 
     assert_eq!(addr1, addr2);
     assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
 
-    unsafe { (*addr2.as_mut_ptr()).sun_path[17] = 127 };
+    addr2.0.sun_path[17] = 127;
     assert_ne!(addr1, addr2);
     assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2));
 }
@@ -180,7 +130,7 @@
     assert_eq!(addr.path(), None);
 
     // Internally, name is null-prefixed (abstract namespace)
-    assert_eq!(unsafe { (*addr.as_ptr()).sun_path[0] }, 0);
+    assert_eq!(addr.0.sun_path[0], 0);
 }
 
 #[test]
@@ -194,7 +144,8 @@
                .expect("socket failed");
     let sockaddr = SockAddr::new_unix(&sockname).unwrap();
     bind(sock, &sockaddr).expect("bind failed");
-    assert_eq!(sockaddr, getsockname(sock).expect("getsockname failed"));
+    assert_eq!(sockaddr.to_str(),
+               getsockname(sock).expect("getsockname failed").to_str());
 }
 
 #[test]
@@ -217,7 +168,7 @@
     use std::thread;
     use super::*;
 
-    const MSG: &[u8] = b"Hello, World!";
+    const MSG: &'static [u8] = b"Hello, World!";
 
     fn sendrecv<Fs, Fr>(rsock: RawFd, ssock: RawFd, f_send: Fs, mut f_recv: Fr) -> Option<SockAddr>
         where
@@ -287,9 +238,9 @@
         use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment};
 
         #[test]
-        // Disable the test under emulation because it fails in Cirrus-CI.  Lack
-        // of QEMU support is suspected.
-        #[cfg_attr(qemu, ignore)]
+        // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack of QEMU
+        // support is suspected.
+        #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
         pub fn gso() {
             require_kernel_version!(udp_offload::gso, ">= 4.18");
 
@@ -341,9 +292,9 @@
         }
 
         #[test]
-        // Disable the test on emulated platforms because it fails in Cirrus-CI.
-        // Lack of QEMU support is suspected.
-        #[cfg_attr(qemu, ignore)]
+        // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack of QEMU
+        // support is suspected.
+        #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
         pub fn gro() {
             require_kernel_version!(udp_offload::gro, ">= 5.3");
 
@@ -393,14 +344,14 @@
 
         let from = sendrecv(rsock, ssock, move |s, m, flags| {
             let iov = [IoVec::from_slice(m)];
-            let mut msgs = vec![
+            let mut msgs = Vec::new();
+            msgs.push(
                 SendMmsgData {
                     iov: &iov,
                     cmsgs: &[],
                     addr: Some(sock_addr),
                     _lt: Default::default(),
-                }
-            ];
+                });
 
             let batch_size = 15;
 
@@ -416,7 +367,7 @@
             }
             sendmmsg(s, msgs.iter(), flags)
                 .map(move |sent_bytes| {
-                    assert!(!sent_bytes.is_empty());
+                    assert!(sent_bytes.len() >= 1);
                     for sent in &sent_bytes {
                         assert_eq!(*sent, m.len());
                     }
@@ -474,7 +425,7 @@
 
         for iov in &iovs {
             msgs.push_back(RecvMmsgData {
-                iov,
+                iov: iov,
                 cmsg_buffer: None,
             })
         };
@@ -546,7 +497,7 @@
 
         for iov in &iovs {
             msgs.push_back(RecvMmsgData {
-                iov,
+                iov: iov,
                 cmsg_buffer: None,
             })
         };
@@ -568,6 +519,7 @@
 // Test error handling of our recvmsg wrapper
 #[test]
 pub fn test_recvmsg_ebadf() {
+    use nix::Error;
     use nix::errno::Errno;
     use nix::sys::socket::{MsgFlags, recvmsg};
     use nix::sys::uio::IoVec;
@@ -576,12 +528,12 @@
     let iov = [IoVec::from_mut_slice(&mut buf[..])];
     let fd = -1;    // Bad file descriptor
     let r = recvmsg(fd, &iov, None, MsgFlags::empty());
-    assert_eq!(r.err().unwrap(), Errno::EBADF);
+    assert_eq!(r.err().unwrap(), Error::Sys(Errno::EBADF));
 }
 
 // Disable the test on emulated platforms due to a bug in QEMU versions <
 // 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
-#[cfg_attr(qemu, ignore)]
+#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
 #[test]
 pub fn test_scm_rights() {
     use nix::sys::uio::IoVec;
@@ -635,10 +587,11 @@
 }
 
 // Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
+#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
 #[cfg(any(target_os = "linux", target_os= "android"))]
-#[cfg_attr(qemu, ignore)]
 #[test]
 pub fn test_af_alg_cipher() {
+    use libc;
     use nix::sys::uio::IoVec;
     use nix::unistd::read;
     use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
@@ -702,14 +655,12 @@
     assert_eq!(decrypted, payload);
 }
 
-// Disable the test on emulated platforms due to not enabled support of AF_ALG
-// in QEMU from rust cross
+// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
+#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
 #[cfg(any(target_os = "linux", target_os= "android"))]
-#[cfg_attr(qemu, ignore)]
 #[test]
 pub fn test_af_alg_aead() {
     use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT};
-    use nix::fcntl::{fcntl, FcntlArg, OFlag};
     use nix::sys::uio::IoVec;
     use nix::unistd::{read, close};
     use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
@@ -788,11 +739,6 @@
 
     // allocate buffer for decrypted data
     let mut decrypted = vec![0u8; payload_len + (assoc_size as usize) + auth_size];
-    // Starting with kernel 4.9, the interface changed slightly such that the
-    // authentication tag memory is only needed in the output buffer for encryption
-    // and in the input buffer for decryption.
-    // Do not block on read, as we may have fewer bytes than buffer size
-    fcntl(session_socket,FcntlArg::F_SETFL(OFlag::O_NONBLOCK)).expect("fcntl non_blocking");
     let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
 
     assert!(num_bytes >= payload_len + (assoc_size as usize));
@@ -811,7 +757,6 @@
         target_os = "netbsd"))]
 #[test]
 pub fn test_sendmsg_ipv4packetinfo() {
-    use cfg_if::cfg_if;
     use nix::sys::uio::IoVec;
     use nix::sys::socket::{socket, sendmsg, bind,
                            AddressFamily, SockType, SockFlag, SockAddr,
@@ -833,21 +778,11 @@
     let iov = [IoVec::from_slice(&slice)];
 
     if let InetAddr::V4(sin) = inet_addr {
-        cfg_if! {
-            if #[cfg(target_os = "netbsd")] {
-                let _dontcare = sin;
-                let pi = libc::in_pktinfo {
-                    ipi_ifindex: 0, /* Unspecified interface */
-                    ipi_addr: libc::in_addr { s_addr: 0 },
-                };
-            } else {
-                let pi = libc::in_pktinfo {
-                    ipi_ifindex: 0, /* Unspecified interface */
-                    ipi_addr: libc::in_addr { s_addr: 0 },
-                    ipi_spec_dst: sin.sin_addr,
-                };
-            }
-        }
+        let pi = libc::in_pktinfo {
+            ipi_ifindex: 0, /* Unspecified interface */
+            ipi_addr: libc::in_addr { s_addr: 0 },
+            ipi_spec_dst: sin.sin_addr,
+        };
 
         let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)];
 
@@ -872,6 +807,7 @@
         target_os = "freebsd"))]
 #[test]
 pub fn test_sendmsg_ipv6packetinfo() {
+    use nix::Error;
     use nix::errno::Errno;
     use nix::sys::uio::IoVec;
     use nix::sys::socket::{socket, sendmsg, bind,
@@ -888,9 +824,12 @@
     let inet_addr = InetAddr::from_std(&std_sa);
     let sock_addr = SockAddr::new_inet(inet_addr);
 
-    if let Err(Errno::EADDRNOTAVAIL) = bind(sock, &sock_addr) {
-        println!("IPv6 not available, skipping test.");
-        return;
+    match bind(sock, &sock_addr) {
+        Err(Error::Sys(Errno::EADDRNOTAVAIL)) => {
+            println!("IPv6 not available, skipping test.");
+            return;
+        },
+        _ => (),
     }
 
     let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
@@ -914,7 +853,7 @@
 /// Tests that passing multiple fds using a single `ControlMessage` works.
 // Disable the test on emulated platforms due to a bug in QEMU versions <
 // 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
-#[cfg_attr(qemu, ignore)]
+#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
 #[test]
 fn test_scm_rights_single_cmsg_multiple_fds() {
     use std::os::unix::net::UnixDatagram;
@@ -923,6 +862,7 @@
     use nix::sys::socket::{ControlMessage, ControlMessageOwned, MsgFlags,
         sendmsg, recvmsg};
     use nix::sys::uio::IoVec;
+    use libc;
 
     let (send, receive) = UnixDatagram::pair().unwrap();
     let thread = thread::spawn(move || {
@@ -1060,11 +1000,13 @@
 /// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single
 /// `sendmsg` call.
 #[cfg(any(target_os = "android", target_os = "linux"))]
-// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
+// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
 // see https://bugs.launchpad.net/qemu/+bug/1781280
-#[cfg_attr(qemu, ignore)]
+#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
 #[test]
 fn test_scm_credentials_and_rights() {
+    use libc;
+
     let space = cmsg_space!(libc::ucred, RawFd);
     test_impl_scm_credentials_and_rights(space);
 }
@@ -1072,9 +1014,9 @@
 /// Ensure that passing a an oversized control message buffer to recvmsg
 /// still works.
 #[cfg(any(target_os = "android", target_os = "linux"))]
-// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
+// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
 // see https://bugs.launchpad.net/qemu/+bug/1781280
-#[cfg_attr(qemu, ignore)]
+#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
 #[test]
 fn test_too_large_cmsgspace() {
     let space = vec![0u8; 1024];
@@ -1195,6 +1137,7 @@
 #[cfg(any(target_os = "macos", target_os = "ios"))]
 #[test]
 pub fn test_syscontrol() {
+    use nix::Error;
     use nix::errno::Errno;
     use nix::sys::socket::{socket, SockAddr, SockType, SockFlag, SockProtocol};
 
@@ -1202,7 +1145,7 @@
                     SockFlag::empty(), SockProtocol::KextControl)
              .expect("socket failed");
     let _sockaddr = SockAddr::new_sys_control(fd, "com.apple.net.utun_control", 0).expect("resolving sys_control name failed");
-    assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Errno::ENOENT));
+    assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Error::Sys(Errno::ENOENT)));
 
     // requires root privileges
     // connect(fd, &sockaddr).expect("connect failed");
@@ -1221,6 +1164,7 @@
     use std::io;
     use std::io::Write;
     use nix::ifaddrs::getifaddrs;
+    use nix::sys::socket::SockAddr;
     use nix::net::if_::*;
 
     let addrs = match getifaddrs() {
@@ -1263,16 +1207,14 @@
     target_os = "netbsd",
 ))]
 // qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(all(
-    qemu,
-    any(
-        target_arch = "mips",
-        target_arch = "mips64",
-        target_arch = "powerpc64",
-    )
+#[cfg_attr(any(
+    target_arch = "mips",
+    target_arch = "mips64",
+    target_arch = "powerpc64",
 ), ignore)]
 #[test]
 pub fn test_recv_ipv4pktinfo() {
+    use libc;
     use nix::sys::socket::sockopt::Ipv4PacketInfo;
     use nix::sys::socket::{bind, SockFlag, SockType};
     use nix::sys::socket::{getsockname, setsockopt, socket};
@@ -1325,15 +1267,18 @@
         );
 
         let mut cmsgs = msg.cmsgs();
-        if let Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) = cmsgs.next() {
-            let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
-            assert_eq!(
-                pktinfo.ipi_ifindex as libc::c_uint,
-                i,
-                "unexpected ifindex (expected {}, got {})",
-                i,
-                pktinfo.ipi_ifindex
-            );
+        match cmsgs.next() {
+            Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) => {
+                let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
+                assert_eq!(
+                    pktinfo.ipi_ifindex as libc::c_uint,
+                    i,
+                    "unexpected ifindex (expected {}, got {})",
+                    i,
+                    pktinfo.ipi_ifindex
+                );
+            }
+            _ => (),
         }
         assert!(cmsgs.next().is_none(), "unexpected additional control msg");
         assert_eq!(msg.bytes, 8);
@@ -1352,16 +1297,14 @@
     target_os = "openbsd",
 ))]
 // qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(all(
-    qemu,
-    any(
-        target_arch = "mips",
-        target_arch = "mips64",
-        target_arch = "powerpc64",
-    )
+#[cfg_attr(any(
+    target_arch = "mips",
+    target_arch = "mips64",
+    target_arch = "powerpc64",
 ), ignore)]
 #[test]
 pub fn test_recvif() {
+    use libc;
     use nix::net::if_::*;
     use nix::sys::socket::sockopt::{Ipv4RecvIf, Ipv4RecvDstAddr};
     use nix::sys::socket::{bind, SockFlag, SockType};
@@ -1445,8 +1388,8 @@
                 _ => panic!("unexpected additional control msg"),
             }
         }
-        assert!(rx_recvif);
-        assert!(rx_recvdstaddr);
+        assert_eq!(rx_recvif, true);
+        assert_eq!(rx_recvdstaddr, true);
         assert_eq!(msg.bytes, 8);
         assert_eq!(
             iovec[0].as_slice(),
@@ -1465,16 +1408,14 @@
     target_os = "openbsd",
 ))]
 // qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(all(
-    qemu,
-    any(
-        target_arch = "mips",
-        target_arch = "mips64",
-        target_arch = "powerpc64",
-    )
+#[cfg_attr(any(
+    target_arch = "mips",
+    target_arch = "mips64",
+    target_arch = "powerpc64",
 ), ignore)]
 #[test]
 pub fn test_recv_ipv6pktinfo() {
+    use libc;
     use nix::net::if_::*;
     use nix::sys::socket::sockopt::Ipv6RecvPacketInfo;
     use nix::sys::socket::{bind, SockFlag, SockType};
@@ -1527,16 +1468,18 @@
         );
 
         let mut cmsgs = msg.cmsgs();
-        if let Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) = cmsgs.next()
-        {
-            let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
-            assert_eq!(
-                pktinfo.ipi6_ifindex as libc::c_uint,
-                i,
-                "unexpected ifindex (expected {}, got {})",
-                i,
-                pktinfo.ipi6_ifindex
-            );
+        match cmsgs.next() {
+            Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) => {
+                let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
+                assert_eq!(
+                    pktinfo.ipi6_ifindex,
+                    i,
+                    "unexpected ifindex (expected {}, got {})",
+                    i,
+                    pktinfo.ipi6_ifindex
+                );
+            }
+            _ => (),
         }
         assert!(cmsgs.next().is_none(), "unexpected additional control msg");
         assert_eq!(msg.bytes, 8);
@@ -1548,9 +1491,10 @@
 }
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
-#[cfg_attr(graviton, ignore = "Not supported by the CI environment")]
 #[test]
 pub fn test_vsock() {
+    use libc;
+    use nix::Error;
     use nix::errno::Errno;
     use nix::sys::socket::{AddressFamily, socket, bind, connect, listen,
                            SockAddr, SockType, SockFlag};
@@ -1563,10 +1507,16 @@
                     SockFlag::empty(), None)
              .expect("socket failed");
 
-    // VMADDR_CID_HYPERVISOR is reserved, so we expect an EADDRNOTAVAIL error.
+    // VMADDR_CID_HYPERVISOR and VMADDR_CID_LOCAL are reserved, so we expect
+    // an EADDRNOTAVAIL error.
     let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_HYPERVISOR, port);
     assert_eq!(bind(s1, &sockaddr).err(),
-               Some(Errno::EADDRNOTAVAIL));
+               Some(Error::Sys(Errno::EADDRNOTAVAIL)));
+
+    let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_LOCAL, port);
+    assert_eq!(bind(s1, &sockaddr).err(),
+               Some(Error::Sys(Errno::EADDRNOTAVAIL)));
+
 
     let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_ANY, port);
     assert_eq!(bind(s1, &sockaddr), Ok(()));
@@ -1591,351 +1541,3 @@
     close(s1).unwrap();
     thr.join().unwrap();
 }
-
-// Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
-// of QEMU support is suspected.
-#[cfg_attr(qemu, ignore)]
-#[cfg(all(target_os = "linux"))]
-#[test]
-fn test_recvmsg_timestampns() {
-    use nix::sys::socket::*;
-    use nix::sys::uio::IoVec;
-    use nix::sys::time::*;
-    use std::time::*;
-
-    // Set up
-    let message = "Ohayō!".as_bytes();
-    let in_socket = socket(
-        AddressFamily::Inet,
-        SockType::Datagram,
-        SockFlag::empty(),
-        None).unwrap();
-    setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
-    let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
-    bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
-    let address = getsockname(in_socket).unwrap();
-    // Get initial time
-    let time0 = SystemTime::now();
-    // Send the message
-    let iov = [IoVec::from_slice(message)];
-    let flags = MsgFlags::empty();
-    let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
-    assert_eq!(message.len(), l);
-    // Receive the message
-    let mut buffer = vec![0u8; message.len()];
-    let mut cmsgspace = nix::cmsg_space!(TimeSpec);
-    let iov = [IoVec::from_mut_slice(&mut buffer)];
-    let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
-    let rtime = match r.cmsgs().next() {
-        Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
-        Some(_) => panic!("Unexpected control message"),
-        None => panic!("No control message")
-    };
-    // Check the final time
-    let time1 = SystemTime::now();
-    // the packet's received timestamp should lie in-between the two system
-    // times, unless the system clock was adjusted in the meantime.
-    let rduration = Duration::new(rtime.tv_sec() as u64,
-    rtime.tv_nsec() as u32);
-    assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
-    assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
-    // Close socket
-    nix::unistd::close(in_socket).unwrap();
-}
-
-// Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
-// of QEMU support is suspected.
-#[cfg_attr(qemu, ignore)]
-#[cfg(all(target_os = "linux"))]
-#[test]
-fn test_recvmmsg_timestampns() {
-    use nix::sys::socket::*;
-    use nix::sys::uio::IoVec;
-    use nix::sys::time::*;
-    use std::time::*;
-
-    // Set up
-    let message = "Ohayō!".as_bytes();
-    let in_socket = socket(
-        AddressFamily::Inet,
-        SockType::Datagram,
-        SockFlag::empty(),
-        None).unwrap();
-    setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
-    let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
-    bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
-    let address = getsockname(in_socket).unwrap();
-    // Get initial time
-    let time0 = SystemTime::now();
-    // Send the message
-    let iov = [IoVec::from_slice(message)];
-    let flags = MsgFlags::empty();
-    let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
-    assert_eq!(message.len(), l);
-    // Receive the message
-    let mut buffer = vec![0u8; message.len()];
-    let mut cmsgspace = nix::cmsg_space!(TimeSpec);
-    let iov = [IoVec::from_mut_slice(&mut buffer)];
-    let mut data = vec![
-        RecvMmsgData {
-            iov,
-            cmsg_buffer: Some(&mut cmsgspace),
-        },
-    ];
-    let r = recvmmsg(in_socket, &mut data, flags, None).unwrap();
-    let rtime = match r[0].cmsgs().next() {
-        Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
-        Some(_) => panic!("Unexpected control message"),
-        None => panic!("No control message")
-    };
-    // Check the final time
-    let time1 = SystemTime::now();
-    // the packet's received timestamp should lie in-between the two system
-    // times, unless the system clock was adjusted in the meantime.
-    let rduration = Duration::new(rtime.tv_sec() as u64,
-    rtime.tv_nsec() as u32);
-    assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
-    assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
-    // Close socket
-    nix::unistd::close(in_socket).unwrap();
-}
-
-// Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
-// of QEMU support is suspected.
-#[cfg_attr(qemu, ignore)]
-#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-#[test]
-fn test_recvmsg_rxq_ovfl() {
-    use nix::Error;
-    use nix::sys::socket::*;
-    use nix::sys::uio::IoVec;
-    use nix::sys::socket::sockopt::{RxqOvfl, RcvBuf};
-
-    let message = [0u8; 2048];
-    let bufsize = message.len() * 2;
-
-    let in_socket = socket(
-        AddressFamily::Inet,
-        SockType::Datagram,
-        SockFlag::empty(),
-        None).unwrap();
-    let out_socket = socket(
-        AddressFamily::Inet,
-        SockType::Datagram,
-        SockFlag::empty(),
-        None).unwrap();
-
-    let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
-    bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
-
-    let address = getsockname(in_socket).unwrap();
-    connect(out_socket, &address).unwrap();
-
-    // Set SO_RXQ_OVFL flag.
-    setsockopt(in_socket, RxqOvfl, &1).unwrap();
-
-    // Set the receiver buffer size to hold only 2 messages.
-    setsockopt(in_socket, RcvBuf, &bufsize).unwrap();
-
-    let mut drop_counter = 0;
-
-    for _ in 0..2 {
-        let iov = [IoVec::from_slice(&message)];
-        let flags = MsgFlags::empty();
-
-        // Send the 3 messages (the receiver buffer can only hold 2 messages)
-        // to create an overflow.
-        for _ in 0..3 {
-            let l = sendmsg(out_socket, &iov, &[], flags, Some(&address)).unwrap();
-            assert_eq!(message.len(), l);
-        }
-
-        // Receive the message and check the drop counter if any.
-        loop {
-            let mut buffer = vec![0u8; message.len()];
-            let mut cmsgspace = nix::cmsg_space!(u32);
-
-            let iov = [IoVec::from_mut_slice(&mut buffer)];
-
-            match recvmsg(
-                in_socket,
-                &iov,
-                Some(&mut cmsgspace),
-                MsgFlags::MSG_DONTWAIT) {
-                Ok(r) => {
-                    drop_counter = match r.cmsgs().next() {
-                        Some(ControlMessageOwned::RxqOvfl(drop_counter)) => drop_counter,
-                        Some(_) => panic!("Unexpected control message"),
-                        None => 0,
-                    };
-                },
-                Err(Error::EAGAIN) => { break; },
-                _ => { panic!("unknown recvmsg() error"); },
-            }
-        }
-    }
-
-    // One packet lost.
-    assert_eq!(drop_counter, 1);
-
-    // Close sockets
-    nix::unistd::close(in_socket).unwrap();
-    nix::unistd::close(out_socket).unwrap();
-}
-
-#[cfg(any(
-    target_os = "linux",
-    target_os = "android",
-))]
-mod linux_errqueue {
-    use nix::sys::socket::*;
-    use super::{FromStr, SocketAddr};
-
-    // Send a UDP datagram to a bogus destination address and observe an ICMP error (v4).
-    //
-    // Disable the test on QEMU because QEMU emulation of IP_RECVERR is broken (as documented on PR
-    // #1514).
-    #[cfg_attr(qemu, ignore)]
-    #[test]
-    fn test_recverr_v4() {
-        #[repr(u8)]
-        enum IcmpTypes {
-            DestUnreach = 3, // ICMP_DEST_UNREACH
-        }
-        #[repr(u8)]
-        enum IcmpUnreachCodes {
-            PortUnreach = 3, // ICMP_PORT_UNREACH
-        }
-
-        test_recverr_impl::<sockaddr_in, _, _>(
-            "127.0.0.1:6800",
-            AddressFamily::Inet,
-            sockopt::Ipv4RecvErr,
-            libc::SO_EE_ORIGIN_ICMP,
-            IcmpTypes::DestUnreach as u8,
-            IcmpUnreachCodes::PortUnreach as u8,
-            // Closure handles protocol-specific testing and returns generic sock_extended_err for
-            // protocol-independent test impl.
-            |cmsg| {
-                if let ControlMessageOwned::Ipv4RecvErr(ext_err, err_addr) = cmsg {
-                    if let Some(origin) = err_addr {
-                        // Validate that our network error originated from 127.0.0.1:0.
-                        assert_eq!(origin.sin_family, AddressFamily::Inet as _);
-                        assert_eq!(Ipv4Addr(origin.sin_addr), Ipv4Addr::new(127, 0, 0, 1));
-                        assert_eq!(origin.sin_port, 0);
-                    } else {
-                        panic!("Expected some error origin");
-                    }
-                    *ext_err
-                } else {
-                    panic!("Unexpected control message {:?}", cmsg);
-                }
-            },
-        )
-    }
-
-    // Essentially the same test as v4.
-    //
-    // Disable the test on QEMU because QEMU emulation of IPV6_RECVERR is broken (as documented on
-    // PR #1514).
-    #[cfg_attr(qemu, ignore)]
-    #[test]
-    fn test_recverr_v6() {
-        #[repr(u8)]
-        enum IcmpV6Types {
-            DestUnreach = 1, // ICMPV6_DEST_UNREACH
-        }
-        #[repr(u8)]
-        enum IcmpV6UnreachCodes {
-            PortUnreach = 4, // ICMPV6_PORT_UNREACH
-        }
-
-        test_recverr_impl::<sockaddr_in6, _, _>(
-            "[::1]:6801",
-            AddressFamily::Inet6,
-            sockopt::Ipv6RecvErr,
-            libc::SO_EE_ORIGIN_ICMP6,
-            IcmpV6Types::DestUnreach as u8,
-            IcmpV6UnreachCodes::PortUnreach as u8,
-            // Closure handles protocol-specific testing and returns generic sock_extended_err for
-            // protocol-independent test impl.
-            |cmsg| {
-                if let ControlMessageOwned::Ipv6RecvErr(ext_err, err_addr) = cmsg {
-                    if let Some(origin) = err_addr {
-                        // Validate that our network error originated from localhost:0.
-                        assert_eq!(origin.sin6_family, AddressFamily::Inet6 as _);
-                        assert_eq!(
-                            Ipv6Addr(origin.sin6_addr),
-                            Ipv6Addr::from_std(&"::1".parse().unwrap()),
-                        );
-                        assert_eq!(origin.sin6_port, 0);
-                    } else {
-                        panic!("Expected some error origin");
-                    }
-                    *ext_err
-                } else {
-                    panic!("Unexpected control message {:?}", cmsg);
-                }
-            },
-        )
-    }
-
-    fn test_recverr_impl<SA, OPT, TESTF>(sa: &str,
-                                         af: AddressFamily,
-                                         opt: OPT,
-                                         ee_origin: u8,
-                                         ee_type: u8,
-                                         ee_code: u8,
-                                         testf: TESTF)
-        where
-            OPT: SetSockOpt<Val = bool>,
-            TESTF: FnOnce(&ControlMessageOwned) -> libc::sock_extended_err,
-    {
-        use nix::errno::Errno;
-        use nix::sys::uio::IoVec;
-
-        const MESSAGE_CONTENTS: &str = "ABCDEF";
-
-        let sock_addr = {
-            let std_sa = SocketAddr::from_str(sa).unwrap();
-            let inet_addr = InetAddr::from_std(&std_sa);
-            SockAddr::new_inet(inet_addr)
-        };
-        let sock = socket(af, SockType::Datagram, SockFlag::SOCK_CLOEXEC, None).unwrap();
-        setsockopt(sock, opt, &true).unwrap();
-        if let Err(e) = sendto(sock, MESSAGE_CONTENTS.as_bytes(), &sock_addr, MsgFlags::empty()) {
-            assert_eq!(e, Errno::EADDRNOTAVAIL);
-            println!("{:?} not available, skipping test.", af);
-            return;
-        }
-
-        let mut buf = [0u8; 8];
-        let iovec = [IoVec::from_mut_slice(&mut buf)];
-        let mut cspace = cmsg_space!(libc::sock_extended_err, SA);
-
-        let msg = recvmsg(sock, &iovec, Some(&mut cspace), MsgFlags::MSG_ERRQUEUE).unwrap();
-        // The sent message / destination associated with the error is returned:
-        assert_eq!(msg.bytes, MESSAGE_CONTENTS.as_bytes().len());
-        assert_eq!(&buf[..msg.bytes], MESSAGE_CONTENTS.as_bytes());
-        // recvmsg(2): "The original destination address of the datagram that caused the error is
-        // supplied via msg_name;" however, this is not literally true.  E.g., an earlier version
-        // of this test used 0.0.0.0 (::0) as the destination address, which was mutated into
-        // 127.0.0.1 (::1).
-        assert_eq!(msg.address, Some(sock_addr));
-
-        // Check for expected control message.
-        let ext_err = match msg.cmsgs().next() {
-            Some(cmsg) => testf(&cmsg),
-            None => panic!("No control message"),
-        };
-
-        assert_eq!(ext_err.ee_errno, libc::ECONNREFUSED as u32);
-        assert_eq!(ext_err.ee_origin, ee_origin);
-        // ip(7): ee_type and ee_code are set from the type and code fields of the ICMP (ICMPv6)
-        // header.
-        assert_eq!(ext_err.ee_type, ee_type);
-        assert_eq!(ext_err.ee_code, ee_code);
-        // ip(7): ee_info contains the discovered MTU for EMSGSIZE errors.
-        assert_eq!(ext_err.ee_info, 0);
-    }
-}
diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs
index 01920fd..5606593 100644
--- a/test/sys/test_sockopt.rs
+++ b/test/sys/test_sockopt.rs
@@ -3,53 +3,12 @@
 #[cfg(any(target_os = "android", target_os = "linux"))]
 use crate::*;
 
-// NB: FreeBSD supports LOCAL_PEERCRED for SOCK_SEQPACKET, but OSX does not.
-#[cfg(any(
-        target_os = "dragonfly",
-        target_os = "freebsd",
-))]
-#[test]
-pub fn test_local_peercred_seqpacket() {
-    use nix::{
-        unistd::{Gid, Uid},
-        sys::socket::socketpair
-    };
-
-    let (fd1, _fd2) = socketpair(AddressFamily::Unix, SockType::SeqPacket, None,
-                                SockFlag::empty()).unwrap();
-    let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap();
-    assert_eq!(xucred.version(), 0);
-    assert_eq!(Uid::from_raw(xucred.uid()), Uid::current());
-    assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
-}
-
-#[cfg(any(
-        target_os = "dragonfly",
-        target_os = "freebsd",
-        target_os = "macos",
-        target_os = "ios"
-))]
-#[test]
-pub fn test_local_peercred_stream() {
-    use nix::{
-        unistd::{Gid, Uid},
-        sys::socket::socketpair
-    };
-
-    let (fd1, _fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None,
-                                SockFlag::empty()).unwrap();
-    let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap();
-    assert_eq!(xucred.version(), 0);
-    assert_eq!(Uid::from_raw(xucred.uid()), Uid::current());
-    assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
-}
-
 #[cfg(target_os = "linux")]
 #[test]
 fn is_so_mark_functional() {
     use nix::sys::socket::sockopt;
 
-    require_capability!("is_so_mark_functional", CAP_NET_ADMIN);
+    require_capability!(CAP_NET_ADMIN);
 
     let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
     setsockopt(s, sockopt::Mark, &1337).unwrap();
@@ -61,7 +20,7 @@
 fn test_so_buf() {
     let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockProtocol::Udp)
              .unwrap();
-    let bufsize: usize = thread_rng().gen_range(4096..131_072);
+    let bufsize: usize = thread_rng().gen_range(4096, 131_072);
     setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap();
     let actual = getsockopt(fd, sockopt::SndBuf).unwrap();
     assert!(actual >= bufsize);
@@ -70,57 +29,6 @@
     assert!(actual >= bufsize);
 }
 
-#[test]
-fn test_so_tcp_maxseg() {
-    use std::net::SocketAddr;
-    use std::str::FromStr;
-    use nix::sys::socket::{accept, bind, connect, listen, InetAddr, SockAddr};
-    use nix::unistd::{close, write};
-
-    let std_sa = SocketAddr::from_str("127.0.0.1:4001").unwrap();
-    let inet_addr = InetAddr::from_std(&std_sa);
-    let sock_addr = SockAddr::new_inet(inet_addr);
-
-    let rsock = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp)
-                .unwrap();
-    bind(rsock, &sock_addr).unwrap();
-    listen(rsock, 10).unwrap();
-    let initial = getsockopt(rsock, sockopt::TcpMaxSeg).unwrap();
-    // Initial MSS is expected to be 536 (https://tools.ietf.org/html/rfc879#section-1) but some
-    // platforms keep it even lower. This might fail if you've tuned your initial MSS to be larger
-    // than 700
-    cfg_if! {
-        if #[cfg(any(target_os = "android", target_os = "linux"))] {
-            let segsize: u32 = 873;
-            assert!(initial < segsize);
-            setsockopt(rsock, sockopt::TcpMaxSeg, &segsize).unwrap();
-        } else {
-            assert!(initial < 700);
-        }
-    }
-
-    // Connect and check the MSS that was advertised
-    let ssock = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp)
-                .unwrap();
-    connect(ssock, &sock_addr).unwrap();
-    let rsess = accept(rsock).unwrap();
-    write(rsess, b"hello").unwrap();
-    let actual = getsockopt(ssock, sockopt::TcpMaxSeg).unwrap();
-    // Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max
-    // TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary.
-    cfg_if! {
-        if #[cfg(any(target_os = "android", target_os = "linux"))] {
-            assert!((segsize - 100) <= actual);
-            assert!(actual <= segsize);
-        } else {
-            assert!(initial < actual);
-            assert!(536 < actual);
-        }
-    }
-    close(rsock).unwrap();
-    close(ssock).unwrap();
-}
-
 // The CI doesn't supported getsockopt and setsockopt on emulated processors.
 // It's beleived that a QEMU issue, the tests run ok on a fully emulated system.
 // Current CI just run the binary with QEMU but the Kernel remains the same as the host.
@@ -166,7 +74,7 @@
 fn test_so_tcp_keepalive() {
     let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp).unwrap();
     setsockopt(fd, sockopt::KeepAlive, &true).unwrap();
-    assert!(getsockopt(fd, sockopt::KeepAlive).unwrap());
+    assert_eq!(getsockopt(fd, sockopt::KeepAlive).unwrap(), true);
 
     #[cfg(any(target_os = "android",
               target_os = "dragonfly",
@@ -186,14 +94,3 @@
         assert_eq!(getsockopt(fd, sockopt::TcpKeepInterval).unwrap(), x + 1);
     }
 }
-
-#[test]
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
-fn test_ttl_opts() {
-    let fd4 = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
-    setsockopt(fd4, sockopt::Ipv4Ttl, &1)
-        .expect("setting ipv4ttl on an inet socket should succeed");
-    let fd6 = socket(AddressFamily::Inet6, SockType::Datagram, SockFlag::empty(), None).unwrap();
-    setsockopt(fd6, sockopt::Ipv6Ttl, &1)
-        .expect("setting ipv6ttl on an inet6 socket should succeed");
-}
diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs
index 4a86154..00aeb2f 100644
--- a/test/sys/test_termios.rs
+++ b/test/sys/test_termios.rs
@@ -1,7 +1,7 @@
 use std::os::unix::prelude::*;
 use tempfile::tempfile;
 
-use nix::fcntl;
+use nix::{Error, fcntl};
 use nix::errno::Errno;
 use nix::pty::openpty;
 use nix::sys::termios::{self, LocalFlags, OutputFlags, tcgetattr};
@@ -19,7 +19,7 @@
 #[test]
 fn test_tcgetattr_pty() {
     // openpty uses ptname(3) internally
-    let _m = crate::PTSNAME_MTX.lock();
+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
 
     let pty = openpty(None, None).expect("openpty failed");
     assert!(termios::tcgetattr(pty.slave).is_ok());
@@ -32,21 +32,21 @@
 fn test_tcgetattr_enotty() {
     let file = tempfile().unwrap();
     assert_eq!(termios::tcgetattr(file.as_raw_fd()).err(),
-               Some(Errno::ENOTTY));
+               Some(Error::Sys(Errno::ENOTTY)));
 }
 
 // Test tcgetattr on an invalid file descriptor
 #[test]
 fn test_tcgetattr_ebadf() {
     assert_eq!(termios::tcgetattr(-1).err(),
-               Some(Errno::EBADF));
+               Some(Error::Sys(Errno::EBADF)));
 }
 
 // Test modifying output flags
 #[test]
 fn test_output_flags() {
     // openpty uses ptname(3) internally
-    let _m = crate::PTSNAME_MTX.lock();
+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Open one pty to get attributes for the second one
     let mut termios = {
@@ -88,7 +88,7 @@
 #[test]
 fn test_local_flags() {
     // openpty uses ptname(3) internally
-    let _m = crate::PTSNAME_MTX.lock();
+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Open one pty to get attributes for the second one
     let mut termios = {
@@ -126,5 +126,5 @@
     let read = read(pty.master, &mut buf).unwrap_err();
     close(pty.master).unwrap();
     close(pty.slave).unwrap();
-    assert_eq!(read, Errno::EAGAIN);
+    assert_eq!(read, Error::Sys(Errno::EAGAIN));
 }
diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs
index c63b581..8d22bf1 100644
--- a/test/sys/test_uio.rs
+++ b/test/sys/test_uio.rs
@@ -14,11 +14,7 @@
 fn test_writev() {
     let mut to_write = Vec::with_capacity(16 * 128);
     for _ in 0..16 {
-        let s: String = thread_rng()
-            .sample_iter(&Alphanumeric)
-            .map(char::from)
-            .take(128)
-            .collect();
+        let s: String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
         let b = s.as_bytes();
         to_write.extend(b.iter().cloned());
     }
@@ -27,7 +23,7 @@
     let mut consumed = 0;
     while consumed < to_write.len() {
         let left = to_write.len() - consumed;
-        let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64..cmp::min(256, left)) };
+        let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
         let b = &to_write[consumed..consumed+slice_len];
         iovecs.push(IoVec::from_slice(b));
         consumed += slice_len;
@@ -61,17 +57,13 @@
 #[test]
 #[cfg(not(target_os = "redox"))]
 fn test_readv() {
-    let s:String = thread_rng()
-        .sample_iter(&Alphanumeric)
-        .map(char::from)
-        .take(128)
-        .collect();
+    let s:String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
     let to_write = s.as_bytes().to_vec();
     let mut storage = Vec::new();
     let mut allocated = 0;
     while allocated < to_write.len() {
         let left = to_write.len() - allocated;
-        let vec_len = if left <= 64 { left } else { thread_rng().gen_range(64..cmp::min(256, left)) };
+        let vec_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
         let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
         storage.push(v);
         allocated += vec_len;
@@ -141,7 +133,7 @@
 }
 
 #[test]
-#[cfg(not(target_os = "redox"))]
+#[cfg(target_os = "linux")]
 fn test_pwritev() {
     use std::io::Read;
 
@@ -171,7 +163,7 @@
 }
 
 #[test]
-#[cfg(not(target_os = "redox"))]
+#[cfg(target_os = "linux")]
 fn test_preadv() {
     use std::io::Write;
 
@@ -205,16 +197,16 @@
 
 #[test]
 #[cfg(target_os = "linux")]
-// qemu-user doesn't implement process_vm_readv/writev on most arches
-#[cfg_attr(qemu, ignore)]
+// FIXME: qemu-user doesn't implement process_vm_readv/writev on most arches
+#[cfg_attr(not(any(target_arch = "x86", target_arch = "x86_64")), ignore)]
 fn test_process_vm_readv() {
     use nix::unistd::ForkResult::*;
     use nix::sys::signal::*;
     use nix::sys::wait::*;
     use crate::*;
 
-    require_capability!("test_process_vm_readv", CAP_SYS_PTRACE);
-    let _m = crate::FORK_MTX.lock();
+    require_capability!(CAP_SYS_PTRACE);
+    let _ = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Pre-allocate memory in the child, since allocation isn't safe
     // post-fork (~= async-signal-safe)
diff --git a/test/sys/test_wait.rs b/test/sys/test_wait.rs
index afe4f42..5bb298e 100644
--- a/test/sys/test_wait.rs
+++ b/test/sys/test_wait.rs
@@ -1,4 +1,4 @@
-use nix::errno::Errno;
+use nix::Error;
 use nix::unistd::*;
 use nix::unistd::ForkResult::*;
 use nix::sys::signal::*;
@@ -8,7 +8,7 @@
 #[test]
 #[cfg(not(target_os = "redox"))]
 fn test_wait_signal() {
-    let _m = crate::FORK_MTX.lock();
+    let _ = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
     match unsafe{fork()}.expect("Error: Fork Failed") {
@@ -25,7 +25,7 @@
 
 #[test]
 fn test_wait_exit() {
-    let _m = crate::FORK_MTX.lock();
+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Safe: Child only calls `_exit`, which is async-signal-safe.
     match unsafe{fork()}.expect("Error: Fork Failed") {
@@ -41,12 +41,12 @@
     let pid = Pid::from_raw(1);
     assert_eq!(WaitStatus::from_raw(pid, 0x0002), Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)));
     assert_eq!(WaitStatus::from_raw(pid, 0x0200), Ok(WaitStatus::Exited(pid, 2)));
-    assert_eq!(WaitStatus::from_raw(pid, 0x7f7f), Err(Errno::EINVAL));
+    assert_eq!(WaitStatus::from_raw(pid, 0x7f7f), Err(Error::invalid_argument()));
 }
 
 #[test]
 fn test_waitstatus_pid() {
-    let _m = crate::FORK_MTX.lock();
+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
     match unsafe{fork()}.unwrap() {
         Child => unsafe { _exit(0) },
@@ -96,8 +96,8 @@
 
     #[test]
     fn test_wait_ptrace() {
-        require_capability!("test_wait_ptrace", CAP_SYS_PTRACE);
-        let _m = crate::FORK_MTX.lock();
+        require_capability!(CAP_SYS_PTRACE);
+        let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
         match unsafe{fork()}.expect("Error: Fork Failed") {
             Child => ptrace_child(),
diff --git a/test/test.rs b/test/test.rs
index aade937..5a5330b 100644
--- a/test/test.rs
+++ b/test/test.rs
@@ -13,8 +13,6 @@
 #[cfg(any(target_os = "android",
           target_os = "linux"))]
 mod test_kmod;
-#[cfg(target_os = "freebsd")]
-mod test_nmount;
 #[cfg(any(target_os = "dragonfly",
           target_os = "freebsd",
           target_os = "fushsia",
@@ -24,7 +22,6 @@
 #[cfg(not(target_os = "redox"))]
 mod test_net;
 mod test_nix_path;
-mod test_resource;
 mod test_poll;
 #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
 mod test_pty;
@@ -43,7 +40,7 @@
 
 use std::os::unix::io::RawFd;
 use std::path::PathBuf;
-use parking_lot::{Mutex, RwLock, RwLockWriteGuard};
+use std::sync::{Mutex, RwLock, RwLockWriteGuard};
 use nix::unistd::{chdir, getcwd, read};
 
 
@@ -84,7 +81,8 @@
 
 impl<'a> DirRestore<'a> {
     fn new() -> Self {
-        let guard = crate::CWD_LOCK.write();
+        let guard = crate::CWD_LOCK.write()
+            .expect("Lock got poisoned by another test");
         DirRestore{
             _g: guard,
             d: getcwd().unwrap(),
diff --git a/test/test_dir.rs b/test/test_dir.rs
index 2940b6e..505277e 100644
--- a/test/test_dir.rs
+++ b/test/test_dir.rs
@@ -4,25 +4,13 @@
 use std::fs::File;
 use tempfile::tempdir;
 
-
-#[cfg(test)]
-fn flags() -> OFlag {
-    #[cfg(target_os = "illumos")]
-    let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC;
-
-    #[cfg(not(target_os = "illumos"))]
-    let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC | OFlag::O_DIRECTORY;
-
-    f
-}
-
 #[test]
-#[allow(clippy::unnecessary_sort_by)]   // False positive
 fn read() {
     let tmp = tempdir().unwrap();
     File::create(&tmp.path().join("foo")).unwrap();
     ::std::os::unix::fs::symlink("foo", tmp.path().join("bar")).unwrap();
-    let mut dir = Dir::open(tmp.path(), flags(), Mode::empty()).unwrap();
+    let mut dir = Dir::open(tmp.path(), OFlag::O_DIRECTORY | OFlag::O_RDONLY | OFlag::O_CLOEXEC,
+                            Mode::empty()).unwrap();
     let mut entries: Vec<_> = dir.iter().map(|e| e.unwrap()).collect();
     entries.sort_by(|a, b| a.file_name().cmp(b.file_name()));
     let entry_names: Vec<_> = entries
@@ -42,7 +30,8 @@
 #[test]
 fn rewind() {
     let tmp = tempdir().unwrap();
-    let mut dir = Dir::open(tmp.path(), flags(), Mode::empty()).unwrap();
+    let mut dir = Dir::open(tmp.path(), OFlag::O_DIRECTORY | OFlag::O_RDONLY | OFlag::O_CLOEXEC,
+                            Mode::empty()).unwrap();
     let entries1: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
     let entries2: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
     let entries3: Vec<_> = dir.into_iter().map(|e| e.unwrap().file_name().to_owned()).collect();
@@ -52,5 +41,5 @@
 
 #[test]
 fn ebadf() {
-    assert_eq!(Dir::from_fd(-1).unwrap_err(), nix::Error::EBADF);
+    assert_eq!(Dir::from_fd(-1).unwrap_err(), nix::Error::Sys(nix::errno::Errno::EBADF));
 }
diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs
index db2acfb..5d1bafe 100644
--- a/test/test_fcntl.rs
+++ b/test/test_fcntl.rs
@@ -1,20 +1,11 @@
 #[cfg(not(target_os = "redox"))]
+use nix::Error;
+#[cfg(not(target_os = "redox"))]
 use nix::errno::*;
 #[cfg(not(target_os = "redox"))]
 use nix::fcntl::{open, OFlag, readlink};
 #[cfg(not(target_os = "redox"))]
 use nix::fcntl::{openat, readlinkat, renameat};
-#[cfg(all(
-    target_os = "linux",
-    target_env = "gnu",
-    any(
-        target_arch = "x86_64",
-        target_arch = "x32",
-        target_arch = "powerpc",
-        target_arch = "s390x"
-    )
-))]
-use nix::fcntl::{RenameFlags, renameat2};
 #[cfg(not(target_os = "redox"))]
 use nix::sys::stat::Mode;
 #[cfg(not(target_os = "redox"))]
@@ -28,6 +19,8 @@
 #[cfg(not(target_os = "redox"))]
 use std::os::unix::fs;
 
+use crate::*;
+
 #[test]
 #[cfg(not(target_os = "redox"))]
 fn test_openat() {
@@ -62,139 +55,13 @@
     let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
     renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap();
     assert_eq!(renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap_err(),
-               Errno::ENOENT);
+               Error::Sys(Errno::ENOENT));
     close(old_dirfd).unwrap();
     close(new_dirfd).unwrap();
     assert!(new_dir.path().join("new").exists());
 }
 
 #[test]
-#[cfg(all(
-    target_os = "linux",
-    target_env = "gnu",
-    any(
-        target_arch = "x86_64",
-        target_arch = "x32",
-        target_arch = "powerpc",
-        target_arch = "s390x"
-    )
-))]
-fn test_renameat2_behaves_like_renameat_with_no_flags() {
-    let old_dir = tempfile::tempdir().unwrap();
-    let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
-    let old_path = old_dir.path().join("old");
-    File::create(&old_path).unwrap();
-    let new_dir = tempfile::tempdir().unwrap();
-    let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
-    renameat2(
-        Some(old_dirfd),
-        "old",
-        Some(new_dirfd),
-        "new",
-        RenameFlags::empty(),
-    )
-    .unwrap();
-    assert_eq!(
-        renameat2(
-            Some(old_dirfd),
-            "old",
-            Some(new_dirfd),
-            "new",
-            RenameFlags::empty()
-        )
-        .unwrap_err(),
-        Errno::ENOENT
-    );
-    close(old_dirfd).unwrap();
-    close(new_dirfd).unwrap();
-    assert!(new_dir.path().join("new").exists());
-}
-
-#[test]
-#[cfg(all(
-    target_os = "linux",
-    target_env = "gnu",
-    any(
-        target_arch = "x86_64",
-        target_arch = "x32",
-        target_arch = "powerpc",
-        target_arch = "s390x"
-    )
-))]
-fn test_renameat2_exchange() {
-    let old_dir = tempfile::tempdir().unwrap();
-    let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
-    let old_path = old_dir.path().join("old");
-    {
-        let mut old_f = File::create(&old_path).unwrap();
-        old_f.write_all(b"old").unwrap();
-    }
-    let new_dir = tempfile::tempdir().unwrap();
-    let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
-    let new_path = new_dir.path().join("new");
-    {
-        let mut new_f = File::create(&new_path).unwrap();
-        new_f.write_all(b"new").unwrap();
-    }
-    renameat2(
-        Some(old_dirfd),
-        "old",
-        Some(new_dirfd),
-        "new",
-        RenameFlags::RENAME_EXCHANGE,
-    )
-    .unwrap();
-    let mut buf = String::new();
-    let mut new_f = File::open(&new_path).unwrap();
-    new_f.read_to_string(&mut buf).unwrap();
-    assert_eq!(buf, "old");
-    buf = "".to_string();
-    let mut old_f = File::open(&old_path).unwrap();
-    old_f.read_to_string(&mut buf).unwrap();
-    assert_eq!(buf, "new");
-    close(old_dirfd).unwrap();
-    close(new_dirfd).unwrap();
-}
-
-#[test]
-#[cfg(all(
-    target_os = "linux",
-    target_env = "gnu",
-    any(
-        target_arch = "x86_64",
-        target_arch = "x32",
-        target_arch = "powerpc",
-        target_arch = "s390x"
-    )
-))]
-fn test_renameat2_noreplace() {
-    let old_dir = tempfile::tempdir().unwrap();
-    let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
-    let old_path = old_dir.path().join("old");
-    File::create(&old_path).unwrap();
-    let new_dir = tempfile::tempdir().unwrap();
-    let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
-    let new_path = new_dir.path().join("new");
-    File::create(&new_path).unwrap();
-    assert_eq!(
-        renameat2(
-            Some(old_dirfd),
-            "old",
-            Some(new_dirfd),
-            "new",
-            RenameFlags::RENAME_NOREPLACE
-        )
-        .unwrap_err(),
-        Errno::EEXIST
-    );
-    close(old_dirfd).unwrap();
-    close(new_dirfd).unwrap();
-    assert!(new_dir.path().join("new").exists());
-    assert!(old_dir.path().join("old").exists());
-}
-
-
-#[test]
 #[cfg(not(target_os = "redox"))]
 fn test_readlink() {
     let tempdir = tempfile::tempdir().unwrap();
@@ -214,18 +81,19 @@
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
 mod linux_android {
+    use std::fs::File;
     use std::io::prelude::*;
-    use std::io::SeekFrom;
+    use std::io::{BufRead, BufReader, SeekFrom};
     use std::os::unix::prelude::*;
+
     use libc::loff_t;
 
     use nix::fcntl::*;
+    use nix::sys::stat::fstat;
     use nix::sys::uio::IoVec;
     use nix::unistd::{close, pipe, read, write};
 
-    use tempfile::tempfile;
-    #[cfg(any(target_os = "linux"))]
-    use tempfile::NamedTempFile;
+    use tempfile::{tempfile, NamedTempFile};
 
     use crate::*;
 
@@ -235,9 +103,11 @@
     /// resulting file is read and should contain the contents `bar`.
     /// The from_offset should be updated by the call to reflect
     /// the 3 bytes read (6).
+    ///
+    /// FIXME: This test is disabled for linux based builds, because Travis
+    /// Linux version is too old for `copy_file_range`.
     #[test]
-    // QEMU does not support copy_file_range. Skip under qemu
-    #[cfg_attr(qemu, ignore)]
+    #[ignore]
     fn test_copy_file_range() {
         const CONTENTS: &[u8] = b"foobarbaz";
 
@@ -319,10 +189,9 @@
 
         let buf1 = b"abcdef";
         let buf2 = b"defghi";
-        let iovecs = vec![
-            IoVec::from_slice(&buf1[0..3]),
-            IoVec::from_slice(&buf2[0..3])
-        ];
+        let mut iovecs = Vec::with_capacity(2);
+        iovecs.push(IoVec::from_slice(&buf1[0..3]));
+        iovecs.push(IoVec::from_slice(&buf2[0..3]));
 
         let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();
 
@@ -337,7 +206,6 @@
         close(wr).unwrap();
     }
 
-    #[cfg(any(target_os = "linux"))]
     #[test]
     fn test_fallocate() {
         let tmp = NamedTempFile::new().unwrap();
@@ -356,11 +224,17 @@
     // they run under QEMU.
 
     #[test]
-    #[cfg(all(target_os = "linux", not(target_env = "musl")))]
+    #[cfg(not(any(target_arch = "aarch64",
+                  target_arch = "arm",
+                  target_arch = "armv7",
+                  target_arch = "x86",
+                  target_arch = "mips",
+                  target_arch = "mips64",
+                  target_arch = "mips64el",
+                  target_arch = "powerpc64",
+                  target_arch = "powerpc64le",
+                  target_env = "musl")))]
     fn test_ofd_write_lock() {
-        use nix::sys::stat::fstat;
-        use std::mem;
-
         let tmp = NamedTempFile::new().unwrap();
 
         let fd = tmp.as_raw_fd();
@@ -373,14 +247,13 @@
         }
         let inode = fstat(fd).expect("fstat failed").st_ino as usize;
 
-        let mut flock: libc::flock = unsafe {
-            mem::zeroed()  // required for Linux/mips
+        let mut flock = libc::flock {
+            l_type: libc::F_WRLCK as libc::c_short,
+            l_whence: libc::SEEK_SET as libc::c_short,
+            l_start: 0,
+            l_len: 0,
+            l_pid: 0,
         };
-        flock.l_type = libc::F_WRLCK as libc::c_short;
-        flock.l_whence = libc::SEEK_SET as libc::c_short;
-        flock.l_start = 0;
-        flock.l_len = 0;
-        flock.l_pid = 0;
         fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed");
         assert_eq!(
             Some(("OFDLCK".to_string(), "WRITE".to_string())),
@@ -393,11 +266,17 @@
     }
 
     #[test]
-    #[cfg(all(target_os = "linux", not(target_env = "musl")))]
+    #[cfg(not(any(target_arch = "aarch64",
+                  target_arch = "arm",
+                  target_arch = "armv7",
+                  target_arch = "x86",
+                  target_arch = "mips",
+                  target_arch = "mips64",
+                  target_arch = "mips64el",
+                  target_arch = "powerpc64",
+                  target_arch = "powerpc64le",
+                  target_env = "musl")))]
     fn test_ofd_read_lock() {
-        use nix::sys::stat::fstat;
-        use std::mem;
-
         let tmp = NamedTempFile::new().unwrap();
 
         let fd = tmp.as_raw_fd();
@@ -410,14 +289,13 @@
         }
         let inode = fstat(fd).expect("fstat failed").st_ino as usize;
 
-        let mut flock: libc::flock = unsafe {
-            mem::zeroed()  // required for Linux/mips
+        let mut flock = libc::flock {
+            l_type: libc::F_RDLCK as libc::c_short,
+            l_whence: libc::SEEK_SET as libc::c_short,
+            l_start: 0,
+            l_len: 0,
+            l_pid: 0,
         };
-        flock.l_type = libc::F_RDLCK as libc::c_short;
-        flock.l_whence = libc::SEEK_SET as libc::c_short;
-        flock.l_start = 0;
-        flock.l_len = 0;
-        flock.l_pid = 0;
         fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed");
         assert_eq!(
             Some(("OFDLCK".to_string(), "READ".to_string())),
@@ -429,13 +307,7 @@
         assert_eq!(None, lock_info(inode));
     }
 
-    #[cfg(all(target_os = "linux", not(target_env = "musl")))]
     fn lock_info(inode: usize) -> Option<(String, String)> {
-        use std::{
-            fs::File,
-            io::BufReader
-        };
-
         let file = File::open("/proc/locks").expect("open /proc/locks failed");
         let buf = BufReader::new(file);
 
@@ -473,16 +345,17 @@
     fn test_success() {
         let tmp = NamedTempFile::new().unwrap();
         let fd = tmp.as_raw_fd();
-        let res = posix_fadvise(fd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED);
+        let res = posix_fadvise(fd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED).unwrap();
 
-        assert!(res.is_ok());
+        assert_eq!(res, 0);
     }
 
     #[test]
     fn test_errno() {
         let (rd, _wr) = pipe().unwrap();
-        let res = posix_fadvise(rd as RawFd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED);
-        assert_eq!(res, Err(Errno::ESPIPE));
+        let errno = posix_fadvise(rd as RawFd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED)
+                                 .unwrap();
+        assert_eq!(errno, Errno::ESPIPE as i32);
     }
 }
 
@@ -512,7 +385,7 @@
                 assert_eq!(tmp.read(&mut data).expect("read failure"), LEN);
                 assert_eq!(&data[..], &[0u8; LEN][..]);
             }
-            Err(Errno::EINVAL) => {
+            Err(nix::Error::Sys(Errno::EINVAL)) => {
                 // POSIX requires posix_fallocate to return EINVAL both for
                 // invalid arguments (i.e. len < 0) and if the operation is not
                 // supported by the file system.
@@ -528,8 +401,12 @@
     fn errno() {
         let (rd, _wr) = pipe().unwrap();
         let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
+        use nix::Error::Sys;
         match err {
-            Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (),
+            Sys(Errno::EINVAL)
+                | Sys(Errno::ENODEV)
+                | Sys(Errno::ESPIPE)
+                | Sys(Errno::EBADF) => (),
             errno =>
                 panic!(
                     "unexpected errno {}",
diff --git a/test/test_kmod/mod.rs b/test/test_kmod/mod.rs
index 8eef538..fb7260b 100644
--- a/test/test_kmod/mod.rs
+++ b/test/test_kmod/mod.rs
@@ -5,7 +5,9 @@
 use crate::*;
 
 fn compile_kernel_module() -> (PathBuf, String, TempDir) {
-    let _m = crate::FORK_MTX.lock();
+    let _m = crate::FORK_MTX
+        .lock()
+        .expect("Mutex got poisoned by another test");
 
     let tmp_dir = tempdir().expect("unable to create temporary build directory");
 
@@ -32,15 +34,16 @@
 use nix::errno::Errno;
 use nix::kmod::{delete_module, DeleteModuleFlags};
 use nix::kmod::{finit_module, init_module, ModuleInitFlags};
+use nix::Error;
 use std::ffi::CString;
 use std::fs::File;
 use std::io::Read;
 
 #[test]
 fn test_finit_and_delete_module() {
-    require_capability!("test_finit_and_delete_module", CAP_SYS_MODULE);
-    let _m0 = crate::KMOD_MTX.lock();
-    let _m1 = crate::CWD_LOCK.read();
+    require_capability!(CAP_SYS_MODULE);
+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
 
@@ -55,10 +58,10 @@
 }
 
 #[test]
-fn test_finit_and_delete_module_with_params() {
-    require_capability!("test_finit_and_delete_module_with_params", CAP_SYS_MODULE);
-    let _m0 = crate::KMOD_MTX.lock();
-    let _m1 = crate::CWD_LOCK.read();
+fn test_finit_and_delete_modul_with_params() {
+    require_capability!(CAP_SYS_MODULE);
+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
 
@@ -77,9 +80,9 @@
 
 #[test]
 fn test_init_and_delete_module() {
-    require_capability!("test_init_and_delete_module", CAP_SYS_MODULE);
-    let _m0 = crate::KMOD_MTX.lock();
-    let _m1 = crate::CWD_LOCK.read();
+    require_capability!(CAP_SYS_MODULE);
+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
 
@@ -87,7 +90,7 @@
     let mut contents: Vec<u8> = Vec::new();
     f.read_to_end(&mut contents)
         .expect("unable to read kernel module content to buffer");
-    init_module(&contents, &CString::new("").unwrap()).expect("unable to load kernel module");
+    init_module(&mut contents, &CString::new("").unwrap()).expect("unable to load kernel module");
 
     delete_module(
         &CString::new(kmod_name).unwrap(),
@@ -97,9 +100,9 @@
 
 #[test]
 fn test_init_and_delete_module_with_params() {
-    require_capability!("test_init_and_delete_module_with_params", CAP_SYS_MODULE);
-    let _m0 = crate::KMOD_MTX.lock();
-    let _m1 = crate::CWD_LOCK.read();
+    require_capability!(CAP_SYS_MODULE);
+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
 
@@ -107,7 +110,7 @@
     let mut contents: Vec<u8> = Vec::new();
     f.read_to_end(&mut contents)
         .expect("unable to read kernel module content to buffer");
-    init_module(&contents, &CString::new("who=Nix number=2015").unwrap())
+    init_module(&mut contents, &CString::new("who=Nix number=2015").unwrap())
         .expect("unable to load kernel module");
 
     delete_module(
@@ -118,23 +121,23 @@
 
 #[test]
 fn test_finit_module_invalid() {
-    require_capability!("test_finit_module_invalid", CAP_SYS_MODULE);
-    let _m0 = crate::KMOD_MTX.lock();
-    let _m1 = crate::CWD_LOCK.read();
+    require_capability!(CAP_SYS_MODULE);
+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let kmod_path = "/dev/zero";
 
     let f = File::open(kmod_path).expect("unable to open kernel module");
     let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
 
-    assert_eq!(result.unwrap_err(), Errno::EINVAL);
+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::EINVAL));
 }
 
 #[test]
 fn test_finit_module_twice_and_delete_module() {
-    require_capability!("test_finit_module_twice_and_delete_module", CAP_SYS_MODULE);
-    let _m0 = crate::KMOD_MTX.lock();
-    let _m1 = crate::CWD_LOCK.read();
+    require_capability!(CAP_SYS_MODULE);
+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
 
@@ -144,7 +147,7 @@
 
     let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
 
-    assert_eq!(result.unwrap_err(), Errno::EEXIST);
+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::EEXIST));
 
     delete_module(
         &CString::new(kmod_name).unwrap(),
@@ -154,11 +157,11 @@
 
 #[test]
 fn test_delete_module_not_loaded() {
-    require_capability!("test_delete_module_not_loaded", CAP_SYS_MODULE);
-    let _m0 = crate::KMOD_MTX.lock();
-    let _m1 = crate::CWD_LOCK.read();
+    require_capability!(CAP_SYS_MODULE);
+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let result = delete_module(&CString::new("hello").unwrap(), DeleteModuleFlags::empty());
 
-    assert_eq!(result.unwrap_err(), Errno::ENOENT);
+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::ENOENT));
 }
diff --git a/test/test_mount.rs b/test/test_mount.rs
index 44287f9..c1b6c8a 100644
--- a/test/test_mount.rs
+++ b/test/test_mount.rs
@@ -21,13 +21,14 @@
     use nix::sys::stat::{self, Mode};
     use nix::unistd::getuid;
 
-    static SCRIPT_CONTENTS: &[u8] = b"#!/bin/sh
+    use tempfile;
+
+    static SCRIPT_CONTENTS: &'static [u8] = b"#!/bin/sh
 exit 23";
 
     const EXPECTED_STATUS: i32 = 23;
 
     const NONE: Option<&'static [u8]> = None;
-    #[allow(clippy::bind_instead_of_map)]   // False positive
     pub fn test_mount_tmpfs_without_flags_allows_rwx() {
         let tempdir = tempfile::tempdir().unwrap();
 
diff --git a/test/test_mq.rs b/test/test_mq.rs
index 430df5d..1667a35 100644
--- a/test/test_mq.rs
+++ b/test/test_mq.rs
@@ -1,7 +1,8 @@
 use std::ffi::CString;
 use std::str;
 
-use nix::errno::Errno;
+use nix::errno::Errno::*;
+use nix::Error::Sys;
 use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_attr_member_t};
 use nix::mqueue::{MqAttr, MQ_OFlag};
 use nix::sys::stat::Mode;
@@ -15,7 +16,7 @@
     let oflag0 = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
     let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
     let r0 = mq_open(mq_name, oflag0, mode, Some(&attr));
-    if let Err(Errno::ENOSYS) = r0 {
+    if let Err(Sys(ENOSYS)) = r0 {
         println!("message queues not supported or module not loaded?");
         return;
     };
@@ -46,7 +47,7 @@
     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
     let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
     let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
-    if let Err(Errno::ENOSYS) = r {
+    if let Err(Sys(ENOSYS)) = r {
         println!("message queues not supported or module not loaded?");
         return;
     };
@@ -60,11 +61,7 @@
 // FIXME: Fix failures for mips in QEMU
 #[test]
 #[cfg(not(any(target_os = "netbsd")))]
-#[cfg_attr(all(
-        qemu,
-        any(target_arch = "mips", target_arch = "mips64")
-    ), ignore
-)]
+#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
 fn test_mq_setattr() {
     use nix::mqueue::{mq_getattr, mq_setattr};
     const MSG_SIZE: mq_attr_member_t = 32;
@@ -73,7 +70,7 @@
     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
     let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
     let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
-    if let Err(Errno::ENOSYS) = r {
+    if let Err(Sys(ENOSYS)) = r {
         println!("message queues not supported or module not loaded?");
         return;
     };
@@ -101,11 +98,7 @@
 // FIXME: Fix failures for mips in QEMU
 #[test]
 #[cfg(not(any(target_os = "netbsd")))]
-#[cfg_attr(all(
-        qemu,
-        any(target_arch = "mips", target_arch = "mips64")
-    ), ignore
-)]
+#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
 fn test_mq_set_nonblocking() {
     use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock};
     const MSG_SIZE: mq_attr_member_t = 32;
@@ -114,7 +107,7 @@
     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
     let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
     let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
-    if let Err(Errno::ENOSYS) = r {
+    if let Err(Sys(ENOSYS)) = r {
         println!("message queues not supported or module not loaded?");
         return;
     };
@@ -139,7 +132,7 @@
     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
     let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
     let r = mq_open(mq_name_opened, oflag, mode, Some(&initial_attr));
-    if let Err(Errno::ENOSYS) = r {
+    if let Err(Sys(ENOSYS)) = r {
         println!("message queues not supported or module not loaded?");
         return;
     };
@@ -149,9 +142,9 @@
     assert_eq!(res_unlink, Ok(()) );
 
     let res_unlink_not_opened = mq_unlink(mq_name_not_opened);
-    assert_eq!(res_unlink_not_opened, Err(Errno::ENOENT) );
+    assert_eq!(res_unlink_not_opened, Err(Sys(ENOENT)) );
 
     mq_close(mqd).unwrap();
     let res_unlink_after_close = mq_unlink(mq_name_opened);
-    assert_eq!(res_unlink_after_close, Err(Errno::ENOENT) );
+    assert_eq!(res_unlink_after_close, Err(Sys(ENOENT)) );
 }
diff --git a/test/test_net.rs b/test/test_net.rs
index 40ecd6b..b8940e7 100644
--- a/test/test_net.rs
+++ b/test/test_net.rs
@@ -8,5 +8,5 @@
 
 #[test]
 fn test_if_nametoindex() {
-    assert!(if_nametoindex(LOOPBACK).is_ok());
+    assert!(if_nametoindex(&LOOPBACK[..]).is_ok());
 }
diff --git a/test/test_nmount.rs b/test/test_nmount.rs
deleted file mode 100644
index 4c74ecf..0000000
--- a/test/test_nmount.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-use crate::*;
-use nix::{
-    errno::Errno,
-    mount::{MntFlags, Nmount, unmount}
-};
-use std::{
-    ffi::CString,
-    fs::File,
-    path::Path
-};
-use tempfile::tempdir;
-
-#[test]
-fn ok() {
-    require_mount!("nullfs");
-
-    let mountpoint = tempdir().unwrap();
-    let target = tempdir().unwrap();
-    let _sentry = File::create(target.path().join("sentry")).unwrap();
-
-    let fstype = CString::new("fstype").unwrap();
-    let nullfs = CString::new("nullfs").unwrap();
-    Nmount::new()
-        .str_opt(&fstype, &nullfs)
-        .str_opt_owned("fspath", mountpoint.path().to_str().unwrap())
-        .str_opt_owned("target", target.path().to_str().unwrap())
-        .nmount(MntFlags::empty()).unwrap();
-    
-    // Now check that the sentry is visible through the mountpoint
-    let exists = Path::exists(&mountpoint.path().join("sentry"));
-
-    // Cleanup the mountpoint before asserting
-    unmount(mountpoint.path(), MntFlags::empty()).unwrap();
-    
-    assert!(exists);
-}
-
-#[test]
-fn bad_fstype() {
-    let mountpoint = tempdir().unwrap();
-    let target = tempdir().unwrap();
-    let _sentry = File::create(target.path().join("sentry")).unwrap();
-
-    let e = Nmount::new()
-        .str_opt_owned("fspath", mountpoint.path().to_str().unwrap())
-        .str_opt_owned("target", target.path().to_str().unwrap())
-        .nmount(MntFlags::empty()).unwrap_err();
-    
-    assert_eq!(e.error(), Errno::EINVAL);
-    assert_eq!(e.errmsg(), Some("Invalid fstype"));
-}
diff --git a/test/test_poll.rs b/test/test_poll.rs
index e4b369f..a5e2d25 100644
--- a/test/test_poll.rs
+++ b/test/test_poll.rs
@@ -1,4 +1,5 @@
 use nix::{
+    Error,
     errno::Errno,
     poll::{PollFlags, poll, PollFd},
     unistd::{write, pipe}
@@ -9,8 +10,8 @@
         loop {
             match $poll_expr {
                 Ok(nfds) => break nfds,
-                Err(Errno::EINTR) => (),
-                Err(e) => panic!("{}", e)
+                Err(Error::Sys(Errno::EINTR)) => (),
+                Err(e) => panic!(e)
             }
         }
     }
@@ -64,19 +65,3 @@
     assert_eq!(nfds, 1);
     assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
 }
-
-#[test]
-fn test_pollfd_fd() {
-    use std::os::unix::io::AsRawFd;
-
-    let pfd = PollFd::new(0x1234, PollFlags::empty());
-    assert_eq!(pfd.as_raw_fd(), 0x1234);
-}
-
-#[test]
-fn test_pollfd_events() {
-    let mut pfd = PollFd::new(-1, PollFlags::POLLIN);
-    assert_eq!(pfd.events(), PollFlags::POLLIN);
-    pfd.set_events(PollFlags::POLLOUT);
-    assert_eq!(pfd.events(), PollFlags::POLLOUT);
-}
diff --git a/test/test_pty.rs b/test/test_pty.rs
index 71932f2..ab347bb 100644
--- a/test/test_pty.rs
+++ b/test/test_pty.rs
@@ -29,7 +29,7 @@
 #[test]
 #[cfg(any(target_os = "android", target_os = "linux"))]
 fn test_ptsname_equivalence() {
-    let _m = crate::PTSNAME_MTX.lock();
+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Open a new PTTY master
     let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
@@ -46,7 +46,7 @@
 #[test]
 #[cfg(any(target_os = "android", target_os = "linux"))]
 fn test_ptsname_copy() {
-    let _m = crate::PTSNAME_MTX.lock();
+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Open a new PTTY master
     let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
@@ -80,7 +80,7 @@
 #[test]
 #[cfg(any(target_os = "android", target_os = "linux"))]
 fn test_ptsname_unique() {
-    let _m = crate::PTSNAME_MTX.lock();
+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Open a new PTTY master
     let master1_fd = posix_openpt(OFlag::O_RDWR).unwrap();
@@ -98,7 +98,7 @@
 
 /// Common setup for testing PTTY pairs
 fn open_ptty_pair() -> (PtyMaster, File) {
-    let _m = crate::PTSNAME_MTX.lock();
+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Open a new PTTY master
     let master = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
@@ -112,30 +112,6 @@
 
     // Open the slave device
     let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()).unwrap();
-
-    #[cfg(target_os = "illumos")]
-    // TODO: rewrite using ioctl!
-    #[allow(clippy::comparison_chain)]
-    {
-        use libc::{ioctl, I_FIND, I_PUSH};
-
-        // On illumos systems, as per pts(7D), one must push STREAMS modules
-        // after opening a device path returned from ptsname().
-        let ptem = b"ptem\0";
-        let ldterm = b"ldterm\0";
-        let r = unsafe { ioctl(slave_fd, I_FIND, ldterm.as_ptr()) };
-        if r < 0 {
-            panic!("I_FIND failure");
-        } else if r == 0 {
-            if unsafe { ioctl(slave_fd, I_PUSH, ptem.as_ptr()) } < 0 {
-                panic!("I_PUSH ptem failure");
-            }
-            if unsafe { ioctl(slave_fd, I_PUSH, ldterm.as_ptr()) } < 0 {
-                panic!("I_PUSH ldterm failure");
-            }
-        }
-    }
-
     let slave = unsafe { File::from_raw_fd(slave_fd) };
 
     (master, slave)
@@ -187,7 +163,7 @@
 #[test]
 fn test_openpty() {
     // openpty uses ptname(3) internally
-    let _m = crate::PTSNAME_MTX.lock();
+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
 
     let pty = openpty(None, None).unwrap();
     assert!(pty.master > 0);
@@ -222,7 +198,7 @@
 #[test]
 fn test_openpty_with_termios() {
     // openpty uses ptname(3) internally
-    let _m = crate::PTSNAME_MTX.lock();
+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Open one pty to get attributes for the second one
     let mut termios = {
@@ -273,15 +249,13 @@
     use nix::sys::signal::*;
     use nix::sys::wait::wait;
     // forkpty calls openpty which uses ptname(3) internally.
-    let _m0 = crate::PTSNAME_MTX.lock();
+    let _m0 = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
     // forkpty spawns a child process
-    let _m1 = crate::FORK_MTX.lock();
+    let _m1 = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
     let string = "naninani\n";
     let echoed_string = "naninani\r\n";
-    let pty = unsafe {
-        forkpty(None, None).unwrap()
-    };
+    let pty = forkpty(None, None).unwrap();
     match pty.fork_result {
         Child => {
             write(STDOUT_FILENO, string.as_bytes()).unwrap();
diff --git a/test/test_ptymaster_drop.rs b/test/test_ptymaster_drop.rs
index a68f81e..ff939b9 100644
--- a/test/test_ptymaster_drop.rs
+++ b/test/test_ptymaster_drop.rs
@@ -12,6 +12,10 @@
     /// race condition.
     #[test]
     #[should_panic(expected = "Closing an invalid file descriptor!")]
+    // In Travis on i686-unknown-linux-musl, this test gets SIGABRT.  I don't
+    // know why.  It doesn't happen on any other target, and it doesn't happen
+    // on my PC.
+    #[cfg_attr(all(target_env = "musl", target_arch = "x86"), ignore)]
     fn test_double_close() {
         let m = posix_openpt(OFlag::O_RDWR).unwrap();
         close(m.as_raw_fd()).unwrap();
diff --git a/test/test_resource.rs b/test/test_resource.rs
deleted file mode 100644
index 5969750..0000000
--- a/test/test_resource.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia", target_os = "illumos")))]
-use nix::sys::resource::{getrlimit, setrlimit, Resource};
-
-/// Tests the RLIMIT_NOFILE functionality of getrlimit(), where the resource RLIMIT_NOFILE refers
-/// to the maximum file descriptor number that can be opened by the process (aka the maximum number
-/// of file descriptors that the process can open, since Linux 4.5).
-///
-/// We first fetch the existing file descriptor maximum values using getrlimit(), then edit the
-/// soft limit to make sure it has a new and distinct value to the hard limit. We then setrlimit()
-/// to put the new soft limit in effect, and then getrlimit() once more to ensure the limits have
-/// been updated.
-#[test]
-#[cfg(not(any(target_os = "redox", target_os = "fuchsia", target_os = "illumos")))]
-pub fn test_resource_limits_nofile() {
-    let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
-
-    let soft_limit = Some(soft_limit.map_or(1024, |v| v - 1));
-    assert_ne!(soft_limit, hard_limit);
-    setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap();
-
-    let (new_soft_limit, _) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
-    assert_eq!(new_soft_limit, soft_limit);
-}
diff --git a/test/test_sendfile.rs b/test/test_sendfile.rs
index b6559d3..3bc7932 100644
--- a/test/test_sendfile.rs
+++ b/test/test_sendfile.rs
@@ -36,28 +36,6 @@
     close(wr).unwrap();
 }
 
-#[cfg(target_os = "linux")]
-#[test]
-fn test_sendfile64_linux() {
-    const CONTENTS: &[u8] = b"abcdef123456";
-    let mut tmp = tempfile().unwrap();
-    tmp.write_all(CONTENTS).unwrap();
-
-    let (rd, wr) = pipe().unwrap();
-    let mut offset: libc::off64_t = 5;
-    let res = sendfile64(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap();
-
-    assert_eq!(2, res);
-
-    let mut buf = [0u8; 1024];
-    assert_eq!(2, read(rd, &mut buf).unwrap());
-    assert_eq!(b"f1", &buf[0..2]);
-    assert_eq!(7, offset);
-
-    close(rd).unwrap();
-    close(wr).unwrap();
-}
-
 #[cfg(target_os = "freebsd")]
 #[test]
 fn test_sendfile_freebsd() {
diff --git a/test/test_stat.rs b/test/test_stat.rs
index 33cf748..0b94666 100644
--- a/test/test_stat.rs
+++ b/test/test_stat.rs
@@ -10,11 +10,10 @@
 use std::path::Path;
 
 #[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-use libc::{S_IFMT, S_IFLNK};
-use libc::mode_t;
+use libc::{S_IFMT, S_IFLNK, mode_t};
 
 #[cfg(not(target_os = "redox"))]
-use nix::fcntl;
+use nix::{fcntl, Error};
 #[cfg(not(target_os = "redox"))]
 use nix::errno::Errno;
 #[cfg(not(target_os = "redox"))]
@@ -43,6 +42,18 @@
 
 #[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
 use nix::Result;
+use tempfile;
+
+#[allow(unused_comparisons)]
+// uid and gid are signed on Windows, but not on other platforms. This function
+// allows warning free compiles on all platforms, and can be removed when
+// expression-level #[allow] is available.
+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+fn valid_uid_gid(stat: FileStat) -> bool {
+    // uid could be 0 for the `root` user. This quite possible when
+    // the tests are being run on a rooted Android device.
+    stat.st_uid >= 0 && stat.st_gid >= 0
+}
 
 #[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
 fn assert_stat_results(stat_result: Result<FileStat>) {
@@ -51,15 +62,13 @@
     assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
     assert!(stats.st_mode > 0);     // must be positive integer
     assert_eq!(stats.st_nlink, 1);   // there links created, must be 1
+    assert!(valid_uid_gid(stats));  // must be positive integers
     assert_eq!(stats.st_size, 0);    // size is 0 because we did not write anything to the file
     assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
     assert!(stats.st_blocks <= 16);  // Up to 16 blocks can be allocated for a blank file
 }
 
 #[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
-// (Android's st_blocks is ulonglong which is always non-negative.)
-#[cfg_attr(target_os = "android", allow(unused_comparisons))]
-#[allow(clippy::absurd_extreme_comparisons)]    // Not absurd on all OSes
 fn assert_lstat_results(stat_result: Result<FileStat>) {
     let stats = stat_result.expect("stat call failed");
     assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
@@ -71,11 +80,13 @@
     // On other platforms they are the same (either both are u16 or u32).
     assert_eq!((stats.st_mode as usize) & (S_IFMT as usize), S_IFLNK as usize); // should be a link
     assert_eq!(stats.st_nlink, 1);   // there links created, must be 1
+    assert!(valid_uid_gid(stats));  // must be positive integers
     assert!(stats.st_size > 0);    // size is > 0 because it points to another file
     assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
 
     // st_blocks depends on whether the machine's file system uses fast
     // or slow symlinks, so just make sure it's not negative
+    // (Android's st_blocks is ulonglong which is always non-negative.)
     assert!(stats.st_blocks >= 0);
 }
 
@@ -148,14 +159,14 @@
     fchmod(file.as_raw_fd(), mode1).unwrap();
 
     let file_stat1 = stat(&filename).unwrap();
-    assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits());
+    assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits());
 
     let mut mode2 = Mode::empty();
     mode2.insert(Mode::S_IROTH);
     fchmod(file.as_raw_fd(), mode2).unwrap();
 
     let file_stat2 = stat(&filename).unwrap();
-    assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits());
+    assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits());
 }
 
 #[test]
@@ -175,7 +186,7 @@
     fchmodat(Some(dirfd), filename, mode1, FchmodatFlags::FollowSymlink).unwrap();
 
     let file_stat1 = stat(&fullpath).unwrap();
-    assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits());
+    assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits());
 
     chdir(tempdir.path()).unwrap();
 
@@ -184,7 +195,7 @@
     fchmodat(None, filename, mode2, FchmodatFlags::FollowSymlink).unwrap();
 
     let file_stat2 = stat(&fullpath).unwrap();
-    assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits());
+    assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits());
 }
 
 /// Asserts that the atime and mtime in a file's metadata match expected values.
@@ -304,55 +315,5 @@
     let dirfd = fcntl::open(&tempdir.path().join(not_dir_filename), fcntl::OFlag::O_CREAT,
                             stat::Mode::empty()).unwrap();
     let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err();
-    assert_eq!(result, Errno::ENOTDIR);
-}
-
-#[test]
-#[cfg(not(any(target_os = "freebsd",
-              target_os = "ios",
-              target_os = "macos",
-              target_os = "redox")))]
-fn test_mknod() {
-    use stat::{lstat, mknod, SFlag};
-
-    let file_name = "test_file";
-    let tempdir = tempfile::tempdir().unwrap();
-    let target = tempdir.path().join(file_name);
-    mknod(&target, SFlag::S_IFREG, Mode::S_IRWXU, 0).unwrap();
-    let mode = lstat(&target).unwrap().st_mode as mode_t;
-    assert!(mode & libc::S_IFREG == libc::S_IFREG);
-    assert!(mode & libc::S_IRWXU == libc::S_IRWXU);
-}
-
-#[test]
-#[cfg(not(any(target_os = "freebsd",
-              target_os = "illumos",
-              target_os = "ios",
-              target_os = "macos",
-              target_os = "redox")))]
-fn test_mknodat() {
-    use fcntl::{AtFlags, OFlag};
-    use nix::dir::Dir;
-    use stat::{fstatat, mknodat, SFlag};
-
-    let file_name = "test_file";
-    let tempdir = tempfile::tempdir().unwrap();
-    let target_dir = Dir::open(tempdir.path(), OFlag::O_DIRECTORY, Mode::S_IRWXU).unwrap();
-    mknodat(
-        target_dir.as_raw_fd(),
-        file_name,
-        SFlag::S_IFREG,
-        Mode::S_IRWXU,
-        0,
-    )
-    .unwrap();
-    let mode = fstatat(
-        target_dir.as_raw_fd(),
-        file_name,
-        AtFlags::AT_SYMLINK_NOFOLLOW,
-    )
-    .unwrap()
-    .st_mode as mode_t;
-    assert!(mode & libc::S_IFREG == libc::S_IFREG);
-    assert!(mode & libc::S_IRWXU == libc::S_IRWXU);
+    assert_eq!(result, Error::Sys(Errno::ENOTDIR));
 }
diff --git a/test/test_time.rs b/test/test_time.rs
index dc307e5..c321352 100644
--- a/test/test_time.rs
+++ b/test/test_time.rs
@@ -6,12 +6,11 @@
     target_os = "emscripten",
 ))]
 use nix::time::clock_getcpuclockid;
-use nix::time::{clock_gettime, ClockId};
+use nix::time::{clock_getres, clock_gettime, ClockId};
 
-#[cfg(not(target_os = "redox"))]
 #[test]
 pub fn test_clock_getres() {
-    assert!(nix::time::clock_getres(ClockId::CLOCK_REALTIME).is_ok());
+    assert!(clock_getres(ClockId::CLOCK_REALTIME).is_ok());
 }
 
 #[test]
@@ -32,7 +31,6 @@
     assert!(clock_gettime(clock_id).is_ok());
 }
 
-#[cfg(not(target_os = "redox"))]
 #[test]
 pub fn test_clock_id_res() {
     assert!(ClockId::CLOCK_REALTIME.res().is_ok());
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index 61062ad..16a8a05 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -1,6 +1,6 @@
 #[cfg(not(target_os = "redox"))]
 use nix::fcntl::{self, open, readlink};
-use nix::fcntl::OFlag;
+use nix::fcntl::{fcntl, FcntlArg, FdFlag, OFlag};
 use nix::unistd::*;
 use nix::unistd::ForkResult::*;
 #[cfg(not(target_os = "redox"))]
@@ -10,25 +10,27 @@
 #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
 use nix::pty::{posix_openpt, grantpt, unlockpt, ptsname};
 use nix::errno::Errno;
-use std::env;
-#[cfg(not(any(target_os = "fuchsia", target_os = "redox")))]
+#[cfg(not(target_os = "redox"))]
+use nix::Error;
+use std::{env, iter};
+#[cfg(not(target_os = "redox"))]
 use std::ffi::CString;
 #[cfg(not(target_os = "redox"))]
 use std::fs::DirBuilder;
 use std::fs::{self, File};
 use std::io::Write;
 use std::os::unix::prelude::*;
-#[cfg(not(any(target_os = "fuchsia", target_os = "redox")))]
+#[cfg(not(target_os = "redox"))]
 use std::path::Path;
 use tempfile::{tempdir, tempfile};
-use libc::{_exit, mode_t, off_t};
+use libc::{_exit, off_t};
 
 use crate::*;
 
 #[test]
 #[cfg(not(any(target_os = "netbsd")))]
 fn test_fork_and_waitpid() {
-    let _m = crate::FORK_MTX.lock();
+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Safe: Child only calls `_exit`, which is signal-safe
     match unsafe{fork()}.expect("Error: Fork Failed") {
@@ -56,7 +58,7 @@
 #[test]
 fn test_wait() {
     // Grab FORK_MTX so wait doesn't reap a different test's child process
-    let _m = crate::FORK_MTX.lock();
+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Safe: Child only calls `_exit`, which is signal-safe
     match unsafe{fork()}.expect("Error: Fork Failed") {
@@ -100,7 +102,7 @@
     mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap();
 
     let stats = stat::stat(&mkfifo_fifo).unwrap();
-    let typ = stat::SFlag::from_bits_truncate(stats.st_mode as mode_t);
+    let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
     assert!(typ == SFlag::S_IFIFO);
 }
 
@@ -116,7 +118,7 @@
     target_os = "macos", target_os = "ios",
     target_os = "android", target_os = "redox")))]
 fn test_mkfifoat_none() {
-    let _m = crate::CWD_LOCK.read();
+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let tempdir = tempdir().unwrap();
     let mkfifoat_fifo = tempdir.path().join("mkfifoat_fifo");
@@ -133,8 +135,6 @@
     target_os = "macos", target_os = "ios",
     target_os = "android", target_os = "redox")))]
 fn test_mkfifoat() {
-    use nix::fcntl;
-
     let tempdir = tempdir().unwrap();
     let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
     let mkfifoat_name = "mkfifoat_name";
@@ -151,10 +151,10 @@
     target_os = "macos", target_os = "ios",
     target_os = "android", target_os = "redox")))]
 fn test_mkfifoat_directory_none() {
-    let _m = crate::CWD_LOCK.read();
+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     // mkfifoat should fail if a directory is given
-    assert!(mkfifoat(None, &env::temp_dir(), Mode::S_IRUSR).is_err());
+    assert!(!mkfifoat(None, &env::temp_dir(), Mode::S_IRUSR).is_ok());
 }
 
 #[test]
@@ -168,7 +168,7 @@
     let mkfifoat_dir = "mkfifoat_dir";
     stat::mkdirat(dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap();
 
-    assert!(mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR).is_err());
+    assert!(!mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR).is_ok());
 }
 
 #[test]
@@ -206,7 +206,7 @@
     // Skip this test when not run as root as `setgroups()` requires root.
     skip_if_not_root!("test_setgroups");
 
-    let _m = crate::GROUPS_MTX.lock();
+    let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Save the existing groups
     let old_groups = getgroups().unwrap();
@@ -224,17 +224,13 @@
 
 #[test]
 // `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
-#[cfg(not(any(target_os = "ios",
-              target_os = "macos",
-              target_os = "redox",
-              target_os = "fuchsia",
-              target_os = "illumos")))]
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "fuchsia")))]
 fn test_initgroups() {
     // Skip this test when not run as root as `initgroups()` and `setgroups()`
     // require root.
     skip_if_not_root!("test_initgroups");
 
-    let _m = crate::GROUPS_MTX.lock();
+    let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
 
     // Save the existing groups
     let old_groups = getgroups().unwrap();
@@ -258,7 +254,7 @@
     setgroups(&old_groups).unwrap();
 }
 
-#[cfg(not(any(target_os = "fuchsia", target_os = "redox")))]
+#[cfg(not(target_os = "redox"))]
 macro_rules! execve_test_factory(
     ($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => (
 
@@ -304,7 +300,7 @@
             skip_if_seccomp!($test_name);
         }
 
-        let m = crate::FORK_MTX.lock();
+        let m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
         // The `exec`d process will write to `writer`, and we'll read that
         // data from `reader`.
         let (reader, writer) = pipe().unwrap();
@@ -370,12 +366,10 @@
         execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
         execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
     } else if #[cfg(any(target_os = "dragonfly",
-                        target_os = "illumos",
                         target_os = "ios",
                         target_os = "macos",
                         target_os = "netbsd",
-                        target_os = "openbsd",
-                        target_os = "solaris"))] {
+                        target_os = "openbsd"))] {
         execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
         // No fexecve() on DragonFly, ios, macos, NetBSD, OpenBSD.
         //
@@ -441,9 +435,9 @@
     // kicks in.  Note: One path cannot be longer than 255 bytes
     // (NAME_MAX) whole path cannot be longer than PATH_MAX (usually
     // 4096 on linux, 1024 on macos)
-    let mut inner_tmp_dir = tmpdir_path;
+    let mut inner_tmp_dir = tmpdir_path.to_path_buf();
     for _ in 0..5 {
-        let newdir = "a".repeat(100);
+        let newdir = iter::repeat("a").take(100).collect::<String>();
         inner_tmp_dir.push(newdir);
         assert!(mkdir(inner_tmp_dir.as_path(), Mode::S_IRWXU).is_ok());
     }
@@ -549,7 +543,7 @@
     if #[cfg(any(target_os = "android", target_os = "linux"))] {
         macro_rules! require_acct{
             () => {
-                require_capability!("test_acct", CAP_SYS_PACCT);
+                require_capability!(CAP_SYS_PACCT);
             }
         }
     } else if #[cfg(target_os = "freebsd")] {
@@ -575,7 +569,7 @@
     use std::process::Command;
     use std::{thread, time};
 
-    let _m = crate::FORK_MTX.lock();
+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
     require_acct!();
 
     let file = NamedTempFile::new().unwrap();
@@ -624,34 +618,15 @@
     assert!(open_max.expect("sysconf failed").is_none())
 }
 
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[test]
-fn test_getresuid() {
-    let resuids = getresuid().unwrap();
-    assert!(resuids.real.as_raw() != libc::uid_t::max_value());
-    assert!(resuids.effective.as_raw() != libc::uid_t::max_value());
-    assert!(resuids.saved.as_raw() != libc::uid_t::max_value());
-}
-
-#[cfg(any(target_os = "android", target_os = "linux"))]
-#[test]
-fn test_getresgid() {
-    let resgids = getresgid().unwrap();
-    assert!(resgids.real.as_raw() != libc::gid_t::max_value());
-    assert!(resgids.effective.as_raw() != libc::gid_t::max_value());
-    assert!(resgids.saved.as_raw() != libc::gid_t::max_value());
-}
-
 // Test that we can create a pair of pipes.  No need to verify that they pass
 // data; that's the domain of the OS, not nix.
 #[test]
 fn test_pipe() {
     let (fd0, fd1) = pipe().unwrap();
-    let m0 = stat::SFlag::from_bits_truncate(stat::fstat(fd0).unwrap().st_mode as mode_t);
+    let m0 = stat::SFlag::from_bits_truncate(stat::fstat(fd0).unwrap().st_mode);
     // S_IFIFO means it's a pipe
     assert_eq!(m0, SFlag::S_IFIFO);
-    let m1 = stat::SFlag::from_bits_truncate(stat::fstat(fd1).unwrap().st_mode as mode_t);
+    let m1 = stat::SFlag::from_bits_truncate(stat::fstat(fd1).unwrap().st_mode);
     assert_eq!(m1, SFlag::S_IFIFO);
 }
 
@@ -661,16 +636,12 @@
           target_os = "dragonfly",
           target_os = "emscripten",
           target_os = "freebsd",
-          target_os = "illumos",
           target_os = "linux",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "redox",
-          target_os = "solaris"))]
+          target_os = "redox"))]
 #[test]
 fn test_pipe2() {
-    use nix::fcntl::{fcntl, FcntlArg, FdFlag};
-
     let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap();
     let f0 = FdFlag::from_bits_truncate(fcntl(fd0, FcntlArg::F_GETFD).unwrap());
     assert!(f0.contains(FdFlag::FD_CLOEXEC));
@@ -735,7 +706,7 @@
     };
 
     // Maybe other tests that fork interfere with this one?
-    let _m = crate::SIGNAL_MTX.lock();
+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
 
     let handler = SigHandler::Handler(alarm_signal_handler);
     let signal_action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty());
@@ -750,7 +721,7 @@
     // Overwriting an alarm should return the old alarm.
     assert_eq!(alarm::set(1), Some(60));
 
-    // We should be woken up after 1 second by the alarm, so we'll sleep for 3
+    // We should be woken up after 1 second by the alarm, so we'll sleep for 2
     // seconds to be sure.
     let starttime = Instant::now();
     loop {
@@ -773,7 +744,7 @@
 #[test]
 #[cfg(not(target_os = "redox"))]
 fn test_canceling_alarm() {
-    let _m = crate::SIGNAL_MTX.lock();
+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
 
     assert_eq!(alarm::cancel(), None);
 
@@ -784,7 +755,7 @@
 #[test]
 #[cfg(not(target_os = "redox"))]
 fn test_symlinkat() {
-    let _m = crate::CWD_LOCK.read();
+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let tempdir = tempdir().unwrap();
 
@@ -883,7 +854,7 @@
 #[test]
 #[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
 fn test_linkat_no_follow_symlink() {
-    let _m = crate::CWD_LOCK.read();
+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let tempdir = tempdir().unwrap();
     let oldfilename = "foo.txt";
@@ -920,7 +891,7 @@
 #[test]
 #[cfg(not(target_os = "redox"))]
 fn test_linkat_follow_symlink() {
-    let _m = crate::CWD_LOCK.read();
+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
 
     let tempdir = tempdir().unwrap();
     let oldfilename = "foo.txt";
@@ -947,9 +918,7 @@
     let newfilestat = stat::stat(&newfilepath).unwrap();
 
     // Check the file type of the new link
-    assert_eq!((stat::SFlag::from_bits_truncate(newfilestat.st_mode as mode_t) & SFlag::S_IFMT),
-        SFlag::S_IFREG
-    );
+    assert!((stat::SFlag::from_bits_truncate(newfilestat.st_mode) & SFlag::S_IFMT) ==  SFlag::S_IFREG);
 
     // Check the number of hard links to the original file
     assert_eq!(newfilestat.st_nlink, 2);
@@ -970,7 +939,7 @@
 
     // Attempt unlink dir at relative path without proper flag
     let err_result = unlinkat(Some(dirfd), dirname, UnlinkatFlags::NoRemoveDir).unwrap_err();
-    assert!(err_result == Errno::EISDIR || err_result == Errno::EPERM);
+    assert!(err_result == Error::Sys(Errno::EISDIR) || err_result == Error::Sys(Errno::EPERM));
  }
 
 #[test]
@@ -1013,7 +982,7 @@
 fn test_access_not_existing() {
     let tempdir = tempdir().unwrap();
     let dir = tempdir.path().join("does_not_exist.txt");
-    assert_eq!(access(&dir, AccessFlags::F_OK).err().unwrap(),
+    assert_eq!(access(&dir, AccessFlags::F_OK).err().unwrap().as_errno().unwrap(),
                Errno::ENOENT);
 }
 
@@ -1025,22 +994,13 @@
     assert!(access(&path, AccessFlags::R_OK | AccessFlags::W_OK).is_ok());
 }
 
-#[cfg(not(target_os = "redox"))]
-#[test]
-fn test_user_into_passwd() {
-    // get the UID of the "nobody" user
-    let nobody = User::from_name("nobody").unwrap().unwrap();
-    let pwd: libc::passwd = nobody.into();
-    let _: User = (&pwd).into();
-}
-
 /// Tests setting the filesystem UID with `setfsuid`.
 #[cfg(any(target_os = "linux", target_os = "android"))]
 #[test]
 fn test_setfsuid() {
     use std::os::unix::fs::PermissionsExt;
     use std::{fs, io, thread};
-    require_capability!("test_setfsuid", CAP_SETUID);
+    require_capability!(CAP_SETUID);
 
     // get the UID of the "nobody" user
     let nobody = User::from_name("nobody").unwrap().unwrap();
@@ -1051,7 +1011,7 @@
     dbg!(&temp_path);
     let temp_path_2 = (&temp_path).to_path_buf();
     let mut permissions = fs::metadata(&temp_path).unwrap().permissions();
-    permissions.set_mode(0o640);
+    permissions.set_mode(640);
 
     // spawn a new thread where to test setfsuid
     thread::spawn(move || {
@@ -1101,13 +1061,13 @@
 fn test_ttyname_not_pty() {
     let fd = File::open("/dev/zero").unwrap();
     assert!(fd.as_raw_fd() > 0);
-    assert_eq!(ttyname(fd.as_raw_fd()), Err(Errno::ENOTTY));
+    assert_eq!(ttyname(fd.as_raw_fd()), Err(Error::Sys(Errno::ENOTTY)));
 }
 
 #[test]
 #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
 fn test_ttyname_invalid_fd() {
-    assert_eq!(ttyname(-1), Err(Errno::EBADF));
+    assert_eq!(ttyname(-1), Err(Error::Sys(Errno::EBADF)));
 }
 
 #[test]