Upgrade rust/crates/nix to 0.21.0

Test: make
Change-Id: Ic8422bfdc4afc11c6c310e67999ec360d92d843d
diff --git a/src/dir.rs b/src/dir.rs
index 7d4ab82..7c35d70 100644
--- a/src/dir.rs
+++ b/src/dir.rs
@@ -53,14 +53,12 @@
 
     /// Converts from a file descriptor, closing it on success or failure.
     pub fn from_fd(fd: RawFd) -> Result<Self> {
-        let d = unsafe { libc::fdopendir(fd) };
-        if d.is_null() {
+        let d = ptr::NonNull::new(unsafe { libc::fdopendir(fd) }).ok_or_else(|| {
             let e = Error::last();
             unsafe { libc::close(fd) };
-            return Err(e);
-        };
-        // Always guaranteed to be non-null by the previous check
-        Ok(Dir(ptr::NonNull::new(d).unwrap()))
+            e
+        })?;
+        Ok(Dir(d))
     }
 
     /// Returns an iterator of `Result<Entry>` which rewinds when finished.
@@ -192,6 +190,7 @@
               target_os = "emscripten",
               target_os = "fuchsia",
               target_os = "haiku",
+              target_os = "illumos",
               target_os = "ios",
               target_os = "l4re",
               target_os = "linux",
@@ -206,6 +205,7 @@
                   target_os = "emscripten",
                   target_os = "fuchsia",
                   target_os = "haiku",
+                  target_os = "illumos",
                   target_os = "ios",
                   target_os = "l4re",
                   target_os = "linux",
@@ -226,6 +226,7 @@
     /// 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),
@@ -236,5 +237,9 @@
             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/errno.rs b/src/errno.rs
index e5c7092..9275feb 100644
--- a/src/errno.rs
+++ b/src/errno.rs
@@ -25,6 +25,10 @@
         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()
+        }
     }
 }
 
@@ -90,7 +94,7 @@
 }
 
 impl ErrnoSentinel for *mut c_void {
-    fn sentinel() -> Self { (-1 as isize) as *mut c_void }
+    fn sentinel() -> Self { -1isize as *mut c_void }
 }
 
 impl ErrnoSentinel for libc::sighandler_t {
@@ -190,114 +194,142 @@
         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",
 
@@ -309,55 +341,70 @@
                   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",
 
@@ -404,6 +451,7 @@
         EMEDIUMTYPE     => "Wrong medium type",
 
         #[cfg(any(target_os = "linux", target_os = "android",
+                  target_os = "illumos", target_os = "solaris",
                   target_os = "fuchsia"))]
         ECANCELED       => "Operation canceled",
 
@@ -427,10 +475,16 @@
                   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",
@@ -445,7 +499,8 @@
         #[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")]
@@ -462,7 +517,8 @@
         #[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 = "redox", target_os = "illumos",
+                  target_os = "solaris"))]
         EOVERFLOW       => "Value too large to be stored in data type",
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
@@ -488,7 +544,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",
@@ -497,7 +553,8 @@
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
                   target_os = "dragonfly", target_os = "ios",
-                  target_os = "openbsd", target_os = "netbsd"))]
+                  target_os = "openbsd", target_os = "netbsd",
+                  target_os = "illumos", target_os = "solaris"))]
         ENOTSUP         => "Operation not supported",
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
@@ -514,13 +571,15 @@
         #[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 = "redox", target_os = "illumos",
+                  target_os = "solaris"))]
         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 = "redox", target_os = "illumos",
+                  target_os = "solaris"))]
         ESTALE          => "Stale NFS file handle",
 
         #[cfg(any(target_os = "macos", target_os = "freebsd",
@@ -588,14 +647,16 @@
         #[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",
@@ -610,7 +671,8 @@
                   target_os = "netbsd", target_os = "redox"))]
         ETIME           => "STREAM ioctl timeout",
 
-        #[cfg(any(target_os = "macos", target_os = "ios"))]
+        #[cfg(any(target_os = "macos", target_os = "ios",
+                  target_os = "illumos", target_os = "solaris"))]
         EOPNOTSUPP      => "Operation not supported on socket",
 
         #[cfg(any(target_os = "macos", target_os = "ios"))]
@@ -627,6 +689,15 @@
 
         #[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",
     }
 }
 
@@ -2199,3 +2270,265 @@
         }
     }
 }
+
+#[cfg(any(target_os = "illumos", target_os = "solaris"))]
+mod consts {
+    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+    #[repr(i32)]
+    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,
+    }
+
+    pub const ELAST: Errno       = Errno::ESTALE;
+    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
+
+    pub 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 d2242da..ce30b7d 100644
--- a/src/fcntl.rs
+++ b/src/fcntl.rs
@@ -34,6 +34,8 @@
         AT_NO_AUTOMOUNT;
         #[cfg(any(target_os = "android", target_os = "linux"))]
         AT_EMPTY_PATH;
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        AT_EACCESS;
     }
 }
 
@@ -48,6 +50,7 @@
         /// 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.
         ///
@@ -63,6 +66,7 @@
                   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",
@@ -162,7 +166,7 @@
 );
 
 // The conversion is not identical on all operating systems.
-#[allow(clippy::identity_conversion)]
+#[allow(clippy::useless_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) }
@@ -172,7 +176,7 @@
 }
 
 // The conversion is not identical on all operating systems.
-#[allow(clippy::identity_conversion)]
+#[allow(clippy::useless_conversion)]
 #[cfg(not(target_os = "redox"))]
 pub fn openat<P: ?Sized + NixPath>(
     dirfd: RawFd,
@@ -248,8 +252,19 @@
     }
     // Uh oh, the result is too long...
     // Let's try to ask lstat how many bytes to allocate.
-    let reported_size = super::sys::stat::lstat(path)
-        .and_then(|x| Ok(x.st_size))
+    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)
         .unwrap_or(0);
     let mut try_size = if reported_size > 0 {
         // Note: even if `lstat`'s apparently valid answer turns out to be
diff --git a/src/features.rs b/src/features.rs
index 6b1cff5..bcda45d 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -94,10 +94,19 @@
     }
 }
 
+#[cfg(any(target_os = "illumos"))]
+mod os {
+    /// Check if the OS supports atomic close-on-exec for sockets
+    pub fn socket_atomic_cloexec() -> bool {
+        true
+    }
+}
+
 #[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"))]
+          target_os = "redox", target_os = "fuchsia",
+          target_os = "solaris"))]
 mod os {
     /// Check if the OS supports atomic close-on-exec for sockets
     pub fn socket_atomic_cloexec() -> bool {
diff --git a/src/kmod.rs b/src/kmod.rs
index 8789cb6..89e577a 100644
--- a/src/kmod.rs
+++ b/src/kmod.rs
@@ -42,7 +42,7 @@
 /// init_module(&mut contents, &CString::new("who=Rust when=Now,12").unwrap()).unwrap();
 /// ```
 ///
-/// See [`man init_module(2)`](http://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
+/// See [`man init_module(2)`](https://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(
@@ -79,7 +79,7 @@
 /// finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()).unwrap();
 /// ```
 ///
-/// See [`man init_module(2)`](http://man7.org/linux/man-pages/man2/init_module.2.html) for more information.
+/// See [`man init_module(2)`](https://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(
@@ -96,7 +96,7 @@
 libc_bitflags!(
     /// Flags used by `delete_module`.
     ///
-    /// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html)
+    /// See [`man delete_module(2)`](https://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;
@@ -115,7 +115,7 @@
 /// delete_module(&CString::new("mymod").unwrap(), DeleteModuleFlags::O_NONBLOCK).unwrap();
 /// ```
 ///
-/// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html) for more information.
+/// See [`man delete_module(2)`](https://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 e62c158..899d3f8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -37,6 +37,7 @@
           target_os = "linux",
           target_os = "macos",
           target_os = "netbsd",
+          target_os = "illumos",
           target_os = "openbsd"))]
 pub mod ifaddrs;
 #[cfg(any(target_os = "android",
diff --git a/src/macros.rs b/src/macros.rs
index feb02ea..7d6ac8d 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -203,16 +203,3 @@
         }
     };
 }
-
-/// 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
-        }
-    }}
-}
diff --git a/src/mount.rs b/src/mount.rs
index 2c54761..edb8afb 100644
--- a/src/mount.rs
+++ b/src/mount.rs
@@ -38,6 +38,7 @@
         MS_KERNMOUNT;
         MS_I_VERSION;
         MS_STRICTATIME;
+        MS_LAZYTIME;
         MS_ACTIVE;
         MS_NOUSER;
         MS_RMT_MASK;
diff --git a/src/mqueue.rs b/src/mqueue.rs
index 0215de5..3e49480 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](http://man7.org/linux/man-pages/man7/mq_overview.7.html)
+//! [Further reading and details on the C API](https://man7.org/linux/man-pages/man7/mq_overview.7.html)
 
 use crate::Result;
 use crate::errno::Errno;
@@ -67,7 +67,7 @@
 
 /// Open a message queue
 ///
-/// See also [`mq_open(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
+/// See also [`mq_open(2)`](https://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)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html)
+/// See also [`mq_unlink(2)`](https://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)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html)
+/// See also [`mq_close(2)`](https://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)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html)
+/// See also [`mq_receive(2)`](https://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)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
+/// See also [`mq_send(2)`](https://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)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html)
+/// See also [`mq_getattr(2)`](https://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](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html)
+/// [Further reading](https://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 {
diff --git a/src/net/if_.rs b/src/net/if_.rs
index 9636488..70349e5 100644
--- a/src/net/if_.rs
+++ b/src/net/if_.rs
@@ -21,39 +21,41 @@
     /// Standard interface flags, used by `getifaddrs`
     pub struct InterfaceFlags: libc::c_int {
         /// Interface is running. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_UP;
         /// Valid broadcast address set. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_BROADCAST;
         /// Internal debugging flag. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_DEBUG;
         /// Interface is a loopback interface. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_LOOPBACK;
         /// Interface is a point-to-point link. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_POINTOPOINT;
         /// Avoid use of trailers. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://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)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://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",
@@ -62,16 +64,16 @@
                   target_os = "solaris"))]
         IFF_RUNNING;
         /// No arp protocol, L2 destination address not set. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_NOARP;
         /// Interface is in promiscuous mode. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_PROMISC;
         /// Receive all multicast packets. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_ALLMULTI;
         /// Master of a load balancing bundle. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://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
@@ -82,10 +84,10 @@
                   target_os = "ios"))]
         IFF_OACTIVE;
         /// Protocol code on board.
-        #[cfg(target_os = "solaris")]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_INTELLIGENT;
         /// Slave of a load balancing bundle. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://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.
@@ -97,7 +99,7 @@
                   target_os = "osx"))]
         IFF_SIMPLEX;
         /// Supports multicast. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html))
         IFF_MULTICAST;
         /// Per link layer defined bit.
         #[cfg(any(target_os = "dragonfly",
@@ -108,10 +110,10 @@
                   target_os = "ios"))]
         IFF_LINK0;
         /// Multicast using broadcast.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_MULTI_BCAST;
         /// Is able to select media type via ifmap. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://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.
@@ -123,10 +125,10 @@
                   target_os = "ios"))]
         IFF_LINK1;
         /// Non-unique address.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_UNNUMBERED;
         /// Auto media selection active. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://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.
@@ -143,15 +145,15 @@
                   target_os = "macos",
                   target_os = "ios"))]
         IFF_ALTPHYS;
-        /// DHCP controlls interface.
-        #[cfg(any(target_os = "solaris"))]
+        /// DHCP controls interface.
+        #[cfg(any(target_os = "solaris", target_os = "illumos"))]
         IFF_DHCPRUNNING;
         /// The addresses are lost when the interface goes down. (see
-        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
+        /// [`netdevice(7)`](https://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 = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_PRIVATE;
         /// Driver signals L1 up. Volatile.
         #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
@@ -163,7 +165,7 @@
         #[cfg(any(target_os = "freebsd"))]
         IFF_CANTCONFIG;
         /// Do not transmit packets.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_NOXMIT;
         /// Driver signals dormant. Volatile.
         #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
@@ -172,7 +174,7 @@
         #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
         IFF_PPROMISC;
         /// Just on-link subnet.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_NOLOCAL;
         /// Echo sent packets. Volatile.
         #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
@@ -181,19 +183,19 @@
         #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
         IFF_MONITOR;
         /// Address is deprecated.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", 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 = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_ADDRCONF;
         /// Interface is in polling mode.
         #[cfg(any(target_os = "dragonfly"))]
         IFF_NPOLLING;
         /// Router on interface.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_ROUTER;
         /// Interface is in polling mode.
         #[cfg(any(target_os = "dragonfly"))]
@@ -202,66 +204,66 @@
         #[cfg(any(target_os = "freebsd"))]
         IFF_DYING;
         /// No NUD on interface.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_NONUD;
         /// Interface is being renamed
         #[cfg(any(target_os = "freebsd"))]
         IFF_RENAMING;
         /// Anycast address.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_ANYCAST;
         /// Don't exchange routing info.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", 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 = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_IPV4;
         /// IPv6 interface.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_IPV6;
         /// in.mpathd test address
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_NOFAILOVER;
         /// Interface has failed
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_FAILED;
         /// Interface is a hot-spare
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_STANDBY;
         /// Functioning but not used
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_INACTIVE;
         /// Interface is offline
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
         IFF_OFFLINE;
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(target_os = "solaris")]
         IFF_COS_ENABLED;
         /// Prefer as source addr.
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(target_os = "solaris")]
         IFF_PREFERRED;
         /// RFC3041
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(target_os = "solaris")]
         IFF_TEMPORARY;
         /// MTU set with SIOCSLIFMTU
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(target_os = "solaris")]
         IFF_FIXEDMTU;
         /// Cannot send / receive packets
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(target_os = "solaris")]
         IFF_VIRTUAL;
         /// Local address in use
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(target_os = "solaris")]
         IFF_DUPLICATE;
         /// IPMP IP interface
-        #[cfg(any(target_os = "solaris"))]
+        #[cfg(target_os = "solaris")]
         IFF_IPMP;
     }
 );
diff --git a/src/poll.rs b/src/poll.rs
index be5bf22..0c3f208 100644
--- a/src/poll.rs
+++ b/src/poll.rs
@@ -51,12 +51,12 @@
         /// Possibilities include:
         ///
         /// *  There is out-of-band data on a TCP socket (see
-        ///    [tcp(7)](http://man7.org/linux/man-pages/man7/tcp.7.html)).
+        ///    [tcp(7)](https://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)](http://man7.org/linux/man-pages/man2/ioctl_tty.2.html)).
+        ///    [ioctl_tty(2)](https://man7.org/linux/man-pages/man2/ioctl_tty.2.html)).
         /// *  A cgroup.events file has been modified (see
-        ///    [cgroups(7)](http://man7.org/linux/man-pages/man7/cgroups.7.html)).
+        ///    [cgroups(7)](https://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
@@ -96,7 +96,7 @@
 }
 
 /// `poll` waits for one of a set of file descriptors to become ready to perform I/O.
-/// ([`poll(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html))
+/// ([`poll(2)`](https://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.
@@ -127,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)`](http://man7.org/linux/man-pages/man2/poll.2.html))
+/// ([`poll(2)`](https://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 d67518f..07e0961 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -92,7 +92,7 @@
 }
 
 /// Grant access to a slave pseudoterminal (see
-/// [`grantpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
+/// [`grantpt(3)`](https://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.
@@ -106,7 +106,7 @@
 }
 
 /// Open a pseudoterminal device (see
-/// [`posix_openpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html))
+/// [`posix_openpt(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html))
 ///
 /// `posix_openpt()` returns a file descriptor to an existing unused pseuterminal master device.
 ///
@@ -152,7 +152,7 @@
 }
 
 /// Get the name of the slave pseudoterminal (see
-/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
+/// [`ptsname(3)`](https://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`.
@@ -179,7 +179,7 @@
 }
 
 /// Get the name of the slave pseudoterminal (see
-/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
+/// [`ptsname(3)`](https://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
@@ -206,7 +206,7 @@
 }
 
 /// Unlock a pseudoterminal master/slave pseudoterminal pair (see
-/// [`unlockpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html))
+/// [`unlockpt(3)`](https://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
@@ -223,7 +223,7 @@
 
 /// Create a new pseudoterminal, returning the slave and master file descriptors
 /// in `OpenptyResult`
-/// (see [`openpty`](http://man7.org/linux/man-pages/man3/openpty.3.html)).
+/// (see [`openpty`](https://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
@@ -297,12 +297,24 @@
 
 /// Create a new pseudoterminal, returning the master file descriptor and forked pid.
 /// in `ForkptyResult`
-/// (see [`forkpty`](http://man7.org/linux/man-pages/man3/forkpty.3.html)).
+/// (see [`forkpty`](https://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`.
-pub fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b 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>>>(
     winsize: T,
     termios: U,
 ) -> Result<ForkptyResult> {
@@ -323,20 +335,15 @@
         .map(|ws| ws as *const Winsize as *mut _)
         .unwrap_or(ptr::null_mut());
 
-    let res = unsafe {
-        libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win)
-    };
+    let res = 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) },
     })?;
 
-    unsafe {
-        Ok(ForkptyResult {
-            master: master.assume_init(),
-            fork_result,
-        })
-    }
+    Ok(ForkptyResult {
+        master: master.assume_init(),
+        fork_result,
+    })
 }
-
diff --git a/src/sched.rs b/src/sched.rs
index 3b48b4a..576eb4a 100644
--- a/src/sched.rs
+++ b/src/sched.rs
@@ -109,7 +109,7 @@
     }
 
     /// `sched_setaffinity` set a thread's CPU affinity mask
-    /// ([`sched_setaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html))
+    /// ([`sched_setaffinity(2)`](https://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.
@@ -142,7 +142,7 @@
     }
 
     /// `sched_getaffinity` get a thread's CPU affinity mask
-    /// ([`sched_getaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_getaffinity.2.html))
+    /// ([`sched_getaffinity(2)`](https://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.
@@ -219,7 +219,7 @@
 
 /// Explicitly yield the processor to other threads.
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html)
+/// [Further reading](https://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 1afdb35..a03caa4 100644
--- a/src/sys/aio.rs
+++ b/src/sys/aio.rs
@@ -25,11 +25,11 @@
 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;
@@ -90,120 +90,31 @@
     AioAllDone = libc::AIO_ALLDONE,
 }
 
-/// 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]>>),
-}
+/// Newtype that adds Send and Sync to libc::aiocb, which contains raw pointers
+#[repr(transparent)]
+struct LibcAiocb(libc::aiocb);
 
-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]>)
-            }
-        }
-    }
-}
+unsafe impl Send for LibcAiocb {}
+unsafe impl Sync for LibcAiocb {}
 
 /// AIO Control Block.
 ///
 /// The basic structure used by all aio functions.  Each `AioCb` represents one
 /// I/O request.
 pub struct AioCb<'a> {
-    aiocb: libc::aiocb,
+    aiocb: LibcAiocb,
     /// 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,
-    /// 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>
+    _buffer: std::marker::PhantomData<&'a [u8]>,
+    _pin: std::marker::PhantomPinned
 }
 
 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.aio_fildes
+        self.aiocb.0.aio_fildes
     }
 
     /// Constructs a new `AioCb` with no associated buffer.
@@ -243,17 +154,39 @@
     /// # }
     /// ```
     pub fn from_fd(fd: RawFd, prio: libc::c_int,
-                    sigev_notify: SigevNotify) -> AioCb<'a> {
+                    sigev_notify: SigevNotify) -> Pin<Box<AioCb<'a>>> {
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        a.aio_offset = 0;
-        a.aio_nbytes = 0;
-        a.aio_buf = null_mut();
+        a.0.aio_offset = 0;
+        a.0.aio_nbytes = 0;
+        a.0.aio_buf = null_mut();
 
-        AioCb {
+        Box::pin(AioCb {
             aiocb: a,
             mutable: false,
             in_progress: false,
-            buffer: Buffer::None
+            _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;
+
+        AioCb {
+            aiocb: a,
+            mutable: true,
+            in_progress: false,
+            _buffer: PhantomData,
+            _pin: std::marker::PhantomPinned
         }
     }
 
@@ -262,8 +195,7 @@
     /// 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.  If the borrow checker gives you trouble, try using
-    /// [`from_boxed_mut_slice`](#method.from_boxed_mut_slice) instead.
+    /// is stack-allocated.
     ///
     /// # Parameters
     ///
@@ -316,210 +248,20 @@
     /// ```
     pub fn from_mut_slice(fd: RawFd, offs: off_t, buf: &'a mut [u8],
                           prio: libc::c_int, sigev_notify: SigevNotify,
-                          opcode: LioOpcode) -> AioCb<'a> {
+                          opcode: LioOpcode) -> Pin<Box<AioCb<'a>>> {
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        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;
+        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;
 
-        AioCb {
+        Box::pin(AioCb {
             aiocb: a,
             mutable: true,
             in_progress: false,
-            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),
-        }
+            _buffer: PhantomData,
+            _pin: std::marker::PhantomPinned
+        })
     }
 
     /// Constructs a new `AioCb` from a mutable raw pointer
@@ -527,8 +269,7 @@
     /// 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 but for some reason the data cannot be
-    /// wrapped in a `struct` that implements `BorrowMut<[u8]>`
+    /// heap allocation is required.
     ///
     /// # Parameters
     ///
@@ -552,28 +293,27 @@
     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) -> AioCb<'a> {
+                           opcode: LioOpcode) -> Pin<Box<AioCb<'a>>> {
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        a.aio_offset = offs;
-        a.aio_nbytes = len;
-        a.aio_buf = buf;
-        a.aio_lio_opcode = opcode as libc::c_int;
+        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;
 
-        AioCb {
+        Box::pin(AioCb {
             aiocb: a,
             mutable: true,
             in_progress: false,
-            buffer: Buffer::None
-        }
+            _buffer: PhantomData,
+            _pin: std::marker::PhantomPinned,
+        })
     }
 
     /// 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 but for
-    /// some reason the data cannot be wrapped in a `struct` that implements
-    /// `Borrow<[u8]>`
+    /// recommended.  It is most useful when heap allocation is required.
     ///
     /// # Parameters
     ///
@@ -597,24 +337,49 @@
     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) -> AioCb<'a> {
+                           opcode: LioOpcode) -> Pin<Box<AioCb<'a>>> {
         let mut a = AioCb::common_init(fd, prio, sigev_notify);
-        a.aio_offset = offs;
-        a.aio_nbytes = len;
+        a.0.aio_offset = offs;
+        a.0.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.aio_buf = buf as *mut c_void;
-        a.aio_lio_opcode = opcode as libc::c_int;
+        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;
 
         AioCb {
             aiocb: a,
             mutable: false,
             in_progress: false,
-            buffer: Buffer::None
+            _buffer: PhantomData,
+            _pin: std::marker::PhantomPinned
         }
     }
 
-    /// Like `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
@@ -657,27 +422,14 @@
     // 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) -> 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,
-        }
+                      opcode: LioOpcode) -> Pin<Box<AioCb>>
+    {
+        Box::pin(AioCb::from_slice_unpinned(fd, offs, buf, prio, sigev_notify,
+                                            opcode))
     }
 
     fn common_init(fd: RawFd, prio: libc::c_int,
-                   sigev_notify: SigevNotify) -> libc::aiocb {
+                   sigev_notify: SigevNotify) -> LibcAiocb {
         // 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
@@ -686,12 +438,18 @@
         a.aio_fildes = fd;
         a.aio_reqprio = prio;
         a.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
-        a
+        LibcAiocb(a)
     }
 
     /// Update the notification settings for an existing `aiocb`
-    pub fn set_sigev_notify(&mut self, sigev_notify: SigevNotify) {
-        self.aiocb.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
+    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();
     }
 
     /// Cancels an outstanding AIO request.
@@ -740,9 +498,13 @@
     ///
     /// # References
     ///
-    /// [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) } {
+    /// [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 {
             libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
             libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
             libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
@@ -751,6 +513,18 @@
         }
     }
 
+    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(Error::from_errno(Errno::from_i32(num))),
+            -1 => Err(Error::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,
@@ -788,28 +562,31 @@
     ///
     /// # References
     ///
-    /// [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)
-        }
+    /// [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()
     }
 
     /// An asynchronous version of `fsync(2)`.
     ///
     /// # References
     ///
-    /// [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 {
+    /// [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;
                 libc::aio_fsync(mode as libc::c_int, p)
-        }).map(|_| {
-            self.in_progress = true;
-        })
+            }).map(|_| {
+                selfp.in_progress = true;
+            })
+        }
     }
 
     /// Returns the `aiocb`'s `LioOpcode` field
@@ -817,7 +594,7 @@
     /// If the value cannot be represented as an `LioOpcode`, returns `None`
     /// instead.
     pub fn lio_opcode(&self) -> Option<LioOpcode> {
-        match self.aiocb.aio_lio_opcode {
+        match self.aiocb.0.aio_lio_opcode {
             libc::LIO_READ => Some(LioOpcode::LIO_READ),
             libc::LIO_WRITE => Some(LioOpcode::LIO_WRITE),
             libc::LIO_NOP => Some(LioOpcode::LIO_NOP),
@@ -831,37 +608,49 @@
     /// number of bytes actually read or written by a completed operation, use
     /// `aio_return` instead.
     pub fn nbytes(&self) -> usize {
-        self.aiocb.aio_nbytes
+        self.aiocb.0.aio_nbytes
     }
 
     /// Returns the file offset stored in the `AioCb`
     pub fn offset(&self) -> off_t {
-        self.aiocb.aio_offset
+        self.aiocb.0.aio_offset
     }
 
     /// Returns the priority of the `AioCb`
     pub fn priority(&self) -> libc::c_int {
-        self.aiocb.aio_reqprio
+        self.aiocb.0.aio_reqprio
     }
 
     /// Asynchronously reads from a file descriptor into a buffer
     ///
     /// # References
     ///
-    /// [aio_read](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_read.html)
-    pub fn read(&mut self) -> Result<()> {
+    /// [aio_read](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_read.html)
+    pub fn read(self: &mut Pin<Box<Self>>) -> Result<()> {
         assert!(self.mutable, "Can't read into an immutable buffer");
-        let p: *mut libc::aiocb = &mut self.aiocb;
-        Errno::result(unsafe {
-            libc::aio_read(p)
+        // 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) }
         }).map(|_| {
-            self.in_progress = true;
+            selfp.in_progress = true;
         })
     }
 
     /// Returns the `SigEvent` stored in the `AioCb`
     pub fn sigevent(&self) -> SigEvent {
-        SigEvent::from(&self.aiocb.aio_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))
+        }
     }
 
     /// Retrieve return status of an asynchronous operation.
@@ -872,28 +661,33 @@
     ///
     /// # References
     ///
-    /// [aio_return](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html)
+    /// [aio_return](https://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(&mut self) -> Result<isize> {
-        let p: *mut libc::aiocb = &mut self.aiocb;
-        self.in_progress = false;
-        Errno::result(unsafe { libc::aio_return(p) })
+    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()
     }
 
     /// Asynchronously writes from a buffer to a file descriptor
     ///
     /// # References
     ///
-    /// [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)
+    /// [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) }
         }).map(|_| {
-            self.in_progress = true;
+            selfp.in_progress = true;
         })
     }
-
 }
 
 /// Cancels outstanding AIO requests for a given file descriptor.
@@ -935,7 +729,7 @@
 ///
 /// # References
 ///
-/// [`aio_cancel`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
+/// [`aio_cancel`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
 pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> {
     match unsafe { libc::aio_cancel(fd, null_mut()) } {
         libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
@@ -970,15 +764,15 @@
 ///     SigevNotify::SigevNone,
 ///     LioOpcode::LIO_NOP);
 /// aiocb.write().unwrap();
-/// aio_suspend(&[&aiocb], None).expect("aio_suspend failed");
+/// aio_suspend(&[aiocb.as_ref()], None).expect("aio_suspend failed");
 /// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
 /// # }
 /// ```
 /// # References
 ///
-/// [`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];
+/// [`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];
     let p = plist as *const *const libc::aiocb;
     let timep = match timeout {
         None    => null::<libc::timespec>(),
@@ -992,7 +786,7 @@
 impl<'a> Debug for AioCb<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         fmt.debug_struct("AioCb")
-            .field("aiocb", &self.aiocb)
+            .field("aiocb", &self.aiocb.0)
             .field("mutable", &self.mutable)
             .field("in_progress", &self.in_progress)
             .finish()
@@ -1018,7 +812,9 @@
     ///
     /// [`AioCb`]: struct.AioCb.html
     /// [`listio`]: #method.listio
-    pub aiocbs: Vec<AioCb<'a>>,
+    // 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>]>,
 
     /// The actual list passed to `libc::lio_listio`.
     ///
@@ -1032,15 +828,23 @@
     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> {
-    /// 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)
-        }
+    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()
     }
 
     /// Submits multiple asynchronous I/O requests with a single system call.
@@ -1069,13 +873,15 @@
     /// # fn main() {
     /// const WBUF: &[u8] = b"abcdef123456";
     /// let mut f = tempfile().unwrap();
-    /// 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 liocb = LioCbBuilder::with_capacity(1)
+    ///     .emplace_slice(
+    ///         f.as_raw_fd(),
+    ///         2,   //offset
+    ///         WBUF,
+    ///         0,   //priority
+    ///         SigevNotify::SigevNone,
+    ///         LioOpcode::LIO_WRITE
+    ///     ).finish();
     /// liocb.listio(LioMode::LIO_WAIT,
     ///              SigevNotify::SigevNone).unwrap();
     /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
@@ -1084,7 +890,7 @@
     ///
     /// # References
     ///
-    /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
+    /// [`lio_listio`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
     ///
     /// [`aio_suspend`]: fn.aio_suspend.html
     /// [`AioCb::error`]: struct.AioCb.html#method.error
@@ -1093,7 +899,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 {
+        for a in &mut self.aiocbs.iter_mut() {
             a.in_progress = true;
             self.list.push(a as *mut AioCb<'a>
                              as *mut libc::aiocb);
@@ -1127,13 +933,15 @@
     /// # fn main() {
     /// const WBUF: &[u8] = b"abcdef123456";
     /// let mut f = tempfile().unwrap();
-    /// 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 liocb = LioCbBuilder::with_capacity(1)
+    ///     .emplace_slice(
+    ///         f.as_raw_fd(),
+    ///         2,   //offset
+    ///         WBUF,
+    ///         0,   //priority
+    ///         SigevNotify::SigevNone,
+    ///         LioOpcode::LIO_WRITE
+    ///     ).finish();
     /// let mut err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
     /// while err == Err(Error::Sys(Errno::EIO)) ||
     ///       err == Err(Error::Sys(Errno::EAGAIN)) {
@@ -1146,9 +954,9 @@
     ///
     /// # References
     ///
-    /// [`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
+    /// [`lio_listio`]: https://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
@@ -1170,10 +978,10 @@
                 // Already collected final status for this operation
                 continue;
             }
-            match a.error() {
+            match a.error_unpinned() {
                 Ok(()) => {
                     // aiocb is complete; collect its status and don't resubmit
-                    self.results[i] = Some(a.aio_return());
+                    self.results[i] = Some(a.aio_return_unpinned());
                 },
                 Err(Error::Sys(Errno::EAGAIN)) => {
                     self.list.push(a as *mut AioCb<'a> as *mut libc::aiocb);
@@ -1202,7 +1010,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()
+            self.aiocbs[i].aio_return_unpinned()
         } else {
             self.results[i].unwrap()
         }
@@ -1218,7 +1026,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()
+            self.aiocbs[i].error_unpinned()
         } else {
             Ok(())
         }
@@ -1234,13 +1042,93 @@
     }
 }
 
+/// 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")))]
-impl<'a> From<Vec<AioCb<'a>>> for LioCb<'a> {
-    fn from(src: Vec<AioCb<'a>>) -> LioCb<'a> {
-        LioCb {
-            list: Vec::with_capacity(src.capacity()),
-            results: Vec::with_capacity(src.capacity()),
-            aiocbs: src,
+#[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 [`LioCb::emplace_slice`] or
+    /// [`LioCb::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();
+        LioCb {
+            aiocbs: self.aiocbs.into(),
+            list: Vec::with_capacity(len),
+            results: Vec::with_capacity(len)
+        }
+    }
+}
+
+#[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/inotify.rs b/src/sys/inotify.rs
index 4880a4a..3f5ae22 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)](http://man7.org/linux/man-pages/man7/inotify.7.html).
-//! 
+//! For more documentation, please read [inotify(7)](https://man7.org/linux/man-pages/man7/inotify.7.html).
+//!
 //! # Examples
 //!
 //! Monitor all events happening in directory "test":
@@ -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)](http://man7.org/linux/man-pages/man7/inotify.7.html).
+/// For more documentation see, [inotify(7)](https://man7.org/linux/man-pages/man7/inotify.7.html).
 #[derive(Debug)]
 pub struct InotifyEvent {
     /// Watch descriptor. This field corresponds to the watch descriptor you
     /// were issued when calling add_watch. It allows you to know which watch
-    /// this event comes from. 
+    /// 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)](http://man7.org/linux/man-pages/man2/inotify_init.2.html).
+    /// For more information see, [inotify_init(2)](https://man7.org/linux/man-pages/man2/inotify_init.2.html).
     pub fn init(flags: InitFlags) -> Result<Inotify> {
         let res = Errno::result(unsafe {
             libc::inotify_init1(flags.bits())
@@ -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)](http://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
+    /// For more information see, [inotify_add_watch(2)](https://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
     pub fn add_watch<P: ?Sized + NixPath>(self,
                                           path: &P,
-                                          mask: AddWatchFlags) 
+                                          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)](http://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
+    /// For more information see, [inotify_rm_watch(2)](https://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 f39c0eb..4ce4d33 100644
--- a/src/sys/ioctl/bsd.rs
+++ b/src/sys/ioctl/bsd.rs
@@ -1,6 +1,12 @@
 /// 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;
@@ -12,6 +18,7 @@
     #[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 8858a9d..203b7d0 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](http://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a
+//! [`ioctl_list` man page](https://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a
 //! large number of `ioctl`s and describes their argument data type.
 //!
 //! Using "bad" `ioctl`s
@@ -232,6 +232,7 @@
 
 #[cfg(any(target_os = "dragonfly",
           target_os = "freebsd",
+          target_os = "illumos",
           target_os = "ios",
           target_os = "macos",
           target_os = "netbsd",
@@ -241,6 +242,7 @@
 
 #[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/mman.rs b/src/sys/mman.rs
index 63a0779..34c7663 100644
--- a/src/sys/mman.rs
+++ b/src/sys/mman.rs
@@ -372,7 +372,7 @@
 
 /// Set protection of memory mapping.
 ///
-/// See [`mprotect(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
+/// See [`mprotect(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
 /// details.
 ///
 /// # Safety
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index 02edfd7..51f0eed 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -28,6 +28,7 @@
           target_os = "redox",
           target_os = "macos",
           target_os = "netbsd",
+          target_os = "illumos",
           target_os = "openbsd"))]
 #[macro_use]
 pub mod ioctl;
diff --git a/src/sys/pthread.rs b/src/sys/pthread.rs
index a4d9825..f730408 100644
--- a/src/sys/pthread.rs
+++ b/src/sys/pthread.rs
@@ -3,7 +3,7 @@
 pub type Pthread = pthread_t;
 
 /// Obtain ID of the calling thread (see
-/// [`pthread_self(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html)
+/// [`pthread_self(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html)
 ///
 /// The thread ID returned by `pthread_self()` is not the same thing as
 /// the kernel thread ID returned by a call to `gettid(2)`.
diff --git a/src/sys/ptrace/bsd.rs b/src/sys/ptrace/bsd.rs
index e85afc7..141dfbc 100644
--- a/src/sys/ptrace/bsd.rs
+++ b/src/sys/ptrace/bsd.rs
@@ -133,16 +133,14 @@
 /// use nix::unistd::Pid;
 /// use nix::sys::signal::Signal;
 /// use nix::sys::wait::*;
-/// 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);
-///         }
-///         _ => {},
+/// // 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/select.rs b/src/sys/select.rs
index a576c7e..5eb6423 100644
--- a/src/sys/select.rs
+++ b/src/sys/select.rs
@@ -50,12 +50,10 @@
     ///
     /// ```
     /// # 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
@@ -64,7 +62,7 @@
     }
 
     /// 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.
@@ -155,7 +153,7 @@
 ///
 /// # References
 ///
-/// [select(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
+/// [select(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
 ///
 /// [`FdSet::highest`]: struct.FdSet.html#method.highest
 pub fn select<'a, N, R, W, E, T>(nfds: N,
@@ -221,7 +219,7 @@
 ///
 /// # References
 ///
-/// [pselect(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html)
+/// [pselect(2)](https://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 84fe2a9..a12c041 100644
--- a/src/sys/sendfile.rs
+++ b/src/sys/sendfile.rs
@@ -18,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.](http://man7.org/linux/man-pages/man2/sendfile.2.html)
+/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
 #[cfg(any(target_os = "android", target_os = "linux"))]
 pub fn sendfile(
     out_fd: RawFd,
@@ -33,6 +33,32 @@
     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 2f8b5fa..bf3f762 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -1,5 +1,5 @@
 // Portions of this file are Copyright 2014 The Rust Project Developers.
-// See http://rust-lang.org/COPYRIGHT.
+// See https://www.rust-lang.org/policies/licenses.
 
 ///! Operating system signals.
 
@@ -619,7 +619,7 @@
     Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
 }
 
-/// Signal management (see [signal(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
+/// Signal management (see [signal(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
 ///
 /// Installs `handler` for the given `signal`, returning the previous signal
 /// handler. `signal` should only be used following another call to `signal` or
@@ -724,8 +724,8 @@
 ///
 /// If both `set` and `oldset` is None, this function is a no-op.
 ///
-/// 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.
+/// For more information, visit the [`pthread_sigmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html),
+/// or [`sigprocmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
 pub fn pthread_sigmask(how: SigmaskHow,
                        set: Option<&SigSet>,
                        oldset: Option<&mut SigSet>) -> Result<()>
@@ -736,7 +736,7 @@
 /// Examine and change blocked signals.
 ///
 /// For more informations see the [`sigprocmask` man
-/// pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
+/// pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
 pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
     if set.is_none() && oldset.is_none() {
         return Ok(())
@@ -765,7 +765,7 @@
 }
 
 /// Send a signal to a process group [(see
-/// killpg(3))](http://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
+/// 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
@@ -850,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,
diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs
index c43b450..1e162cf 100644
--- a/src/sys/signalfd.rs
+++ b/src/sys/signalfd.rs
@@ -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](http://man7.org/linux/man-pages/man2/signalfd.2.html)
+/// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html)
 pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
     unsafe {
         Errno::result(libc::signalfd(fd as libc::c_int, mask.as_ref(), flags.bits()))
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index 2299c57..6a0bc9a 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -1,6 +1,7 @@
 use super::sa_family_t;
 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};
@@ -20,6 +21,7 @@
           target_os = "ios",
           target_os = "linux",
           target_os = "macos",
+          target_os = "illumos",
           target_os = "netbsd",
           target_os = "openbsd",
           target_os = "fuchsia"))]
@@ -32,17 +34,21 @@
 #[repr(i32)]
 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
 pub enum AddressFamily {
-    /// Local communication (see [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html))
+    /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html))
     Unix = libc::AF_UNIX,
-    /// IPv4 Internet protocols (see [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html))
+    /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html))
     Inet = libc::AF_INET,
-    /// IPv6 Internet protocols (see [`ipv6(7)`](http://man7.org/linux/man-pages/man7/ipv6.7.html))
+    /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html))
     Inet6 = libc::AF_INET6,
-    /// Kernel user interface device (see [`netlink(7)`](http://man7.org/linux/man-pages/man7/netlink.7.html))
+    /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html))
     #[cfg(any(target_os = "android", target_os = "linux"))]
     Netlink = libc::AF_NETLINK,
-    /// 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"))]
+    /// 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"))]
     Packet = libc::AF_PACKET,
     /// KEXT Controls and Notifications
     #[cfg(any(target_os = "ios", target_os = "macos"))]
@@ -61,7 +67,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)`](http://man7.org/linux/man-pages/man7/x25.7.html))
+    /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html))
     #[cfg(any(target_os = "android", target_os = "linux"))]
     X25 = libc::AF_X25,
     #[cfg(any(target_os = "android", target_os = "linux"))]
@@ -98,12 +104,16 @@
     Can = libc::AF_CAN,
     #[cfg(any(target_os = "android", target_os = "linux"))]
     Tipc = libc::AF_TIPC,
-    #[cfg(not(any(target_os = "ios", target_os = "macos")))]
+    #[cfg(not(any(target_os = "illumos",
+                  target_os = "ios",
+                  target_os = "macos",
+                  target_os = "solaris")))]
     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,
@@ -190,6 +200,7 @@
               target_os = "freebsd",
               target_os = "ios",
               target_os = "macos",
+              target_os = "illumos",
               target_os = "netbsd",
               target_os = "openbsd"))]
     Link = libc::AF_LINK,
@@ -214,7 +225,7 @@
               target_os = "netbsd",
               target_os = "openbsd"))]
     Natm = libc::AF_NATM,
-    /// Unspecified address family, (see [`getaddrinfo(3)`](http://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
+    /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html))
     #[cfg(any(target_os = "android", target_os = "linux"))]
     Unspec = libc::AF_UNSPEC,
 }
@@ -241,6 +252,7 @@
                       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"))]
@@ -645,6 +657,7 @@
               target_os = "ios",
               target_os = "linux",
               target_os = "macos",
+              target_os = "illumos",
               target_os = "netbsd",
               target_os = "openbsd"))]
     Link(LinkAddr),
@@ -699,6 +712,7 @@
                       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"))]
@@ -744,6 +758,7 @@
                           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));
@@ -830,6 +845,7 @@
                       target_os = "freebsd",
                       target_os = "ios",
                       target_os = "macos",
+                      target_os = "illumos",
                       target_os = "netbsd",
                       target_os = "openbsd"))]
             SockAddr::Link(LinkAddr(ref addr)) => (
@@ -869,6 +885,7 @@
                       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"))]
@@ -1118,6 +1135,7 @@
           target_os = "freebsd",
           target_os = "ios",
           target_os = "macos",
+          target_os = "illumos",
           target_os = "netbsd",
           target_os = "openbsd"))]
 mod datalink {
@@ -1129,6 +1147,7 @@
 
     impl LinkAddr {
         /// Total length of sockaddr
+        #[cfg(not(target_os = "illumos"))]
         pub fn len(&self) -> usize {
             self.0.sdl_len as usize
         }
@@ -1280,6 +1299,7 @@
               target_os = "linux",
               target_os = "macos",
               target_os = "netbsd",
+              target_os = "illumos",
               target_os = "openbsd"))]
     use super::*;
 
@@ -1324,6 +1344,28 @@
         };
     }
 
+    #[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() {
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index 11ed329..6907046 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -1,12 +1,15 @@
 //! Socket interface functions
 //!
-//! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
+//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html)
 use cfg_if::cfg_if;
 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;
 
@@ -19,6 +22,7 @@
  *
  */
 
+#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
 pub use self::addr::{
     AddressFamily,
     SockAddr,
@@ -29,6 +33,17 @@
     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"))]
@@ -80,9 +95,9 @@
 #[repr(i32)]
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub enum SockProtocol {
-    /// TCP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
+    /// TCP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html))
     Tcp = libc::IPPROTO_TCP,
-    /// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
+    /// UDP protocol ([ip(7)](https://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))
@@ -159,6 +174,7 @@
         #[cfg(any(target_os = "android",
                   target_os = "dragonfly",
                   target_os = "freebsd",
+                  target_os = "illumos",
                   target_os = "linux",
                   target_os = "netbsd",
                   target_os = "openbsd"))]
@@ -167,6 +183,7 @@
         #[cfg(any(target_os = "android",
                   target_os = "dragonfly",
                   target_os = "freebsd",
+                  target_os = "illumos",
                   target_os = "linux",
                   target_os = "netbsd",
                   target_os = "openbsd"))]
@@ -202,7 +219,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)](http://man7.org/linux/man-pages/man2/open.2.html)),
+        /// description (see [open(2)](https://man7.org/linux/man-pages/man2/open.2.html)),
         /// which will affect all threads in
         /// the calling process and as well as other processes that hold
         /// file descriptors referring to the same open file description.
@@ -230,7 +247,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)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
+        /// [open(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html).
         ///
         /// Only used in [`recvmsg`](fn.recvmsg.html) function.
         #[cfg(any(target_os = "android",
@@ -401,13 +418,11 @@
 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 {
-                    CMSG_SPACE(mem::size_of::<$x>() as c_uint)
+                    $crate::sys::socket::CMSG_SPACE(::std::mem::size_of::<$x>() as $crate::sys::socket::c_uint)
                 } as usize;
             )*
             Vec::<u8>::with_capacity(space)
@@ -467,7 +482,7 @@
 /// A type-safe wrapper around a single control message, as used with
 /// [`recvmsg`](#fn.recvmsg).
 ///
-/// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
+/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
 //  Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and
 //  sendmsg.  However, on some platforms the messages returned by recvmsg may be
 //  unaligned.  ControlMessageOwned takes those messages by copy, obviating any
@@ -495,6 +510,7 @@
     ///
     /// # Examples
     ///
+    /// ```
     /// # #[macro_use] extern crate nix;
     /// # use nix::sys::socket::*;
     /// # use nix::sys::uio::IoVec;
@@ -542,6 +558,11 @@
     /// # }
     /// ```
     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",
@@ -633,6 +654,11 @@
                 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",
@@ -684,7 +710,7 @@
             },
             (_, _) => {
                 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)
             }
         }
@@ -695,14 +721,14 @@
 /// [`sendmsg`](#fn.sendmsg).  More types may be added to this enum; do not
 /// exhaustively pattern-match it.
 ///
-/// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
+/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html)
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum ControlMessage<'a> {
     /// A message of type `SCM_RIGHTS`, containing an array of file
     /// descriptors passed between processes.
     ///
     /// See the description in the "Ancillary messages" section of the
-    /// [unix(7) man page](http://man7.org/linux/man-pages/man7/unix.7.html).
+    /// [unix(7) man page](https://man7.org/linux/man-pages/man7/unix.7.html).
     ///
     /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
     /// recommended since it causes platform-dependent behaviour: It might
@@ -719,7 +745,7 @@
     /// processes are verified by the kernel.
     ///
     /// For further information, please refer to the
-    /// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page.
+    /// [`unix(7)`](https://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
@@ -781,7 +807,7 @@
     /// Configure the sending addressing and interface for v4
     ///
     /// For further information, please refer to the
-    /// [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html) man page.
+    /// [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html) man page.
     #[cfg(any(target_os = "linux",
               target_os = "macos",
               target_os = "netbsd",
@@ -792,7 +818,7 @@
     /// Configure the sending addressing and interface for v6
     ///
     /// For further information, please refer to the
-    /// [`ipv6(7)`](http://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
+    /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page.
     #[cfg(any(target_os = "linux",
               target_os = "macos",
               target_os = "netbsd",
@@ -1089,23 +1115,22 @@
 
     let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);
 
-    let mut cmsgs_buffer = vec![0u8; 0];
+    let mut cmsgs_buffers = Vec::<Vec<u8>>::with_capacity(reserve_items);
 
     for d in iter {
-        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);
+        let capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum();
+        let mut cmsgs_buffer = vec![0u8; capacity];
 
         output.push(libc::mmsghdr {
             msg_hdr: pack_mhdr_to_send(
-                &mut cmsgs_buffer[cmsgs_start..],
+                &mut cmsgs_buffer,
                 &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 _) };
@@ -1378,7 +1403,7 @@
 /// * `flags`:          Optional flags passed directly to the operating system.
 ///
 /// # References
-/// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
+/// [recvmsg(2)](https://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>>
@@ -1406,7 +1431,7 @@
 /// protocols may exist, in which case a particular protocol must be
 /// specified in this manner.
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
 pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
     let protocol = match protocol.into() {
         None => 0,
@@ -1426,7 +1451,7 @@
 
 /// Create a pair of connected sockets
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
 pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
                   flags: SockFlag) -> Result<(RawFd, RawFd)> {
     let protocol = match protocol.into() {
@@ -1450,7 +1475,7 @@
 
 /// Listen for connections on a socket
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
 pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
     let res = unsafe { libc::listen(sockfd, backlog as c_int) };
 
@@ -1459,7 +1484,7 @@
 
 /// Bind a name to a socket
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
+/// [Further reading](https://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();
@@ -1471,7 +1496,7 @@
 
 /// Accept a connection on a socket
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
 pub fn accept(sockfd: RawFd) -> Result<RawFd> {
     let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
 
@@ -1480,8 +1505,15 @@
 
 /// Accept a connection on a socket
 ///
-/// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
-#[cfg(any(target_os = "android",
+/// [Further reading](https://man7.org/linux/man-pages/man2/accept.2.html)
+#[cfg(any(all(
+            target_os = "android",
+            any(
+                target_arch = "aarch64",
+                target_arch = "x86",
+                target_arch = "x86_64"
+            )
+          ),
           target_os = "freebsd",
           target_os = "linux",
           target_os = "openbsd"))]
@@ -1493,7 +1525,7 @@
 
 /// Initiate a connection on a socket
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
+/// [Further reading](https://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();
@@ -1506,7 +1538,7 @@
 /// Receive data from a connection-oriented socket. Returns the number of
 /// bytes read
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
 pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
     unsafe {
         let ret = libc::recv(
@@ -1523,7 +1555,7 @@
 /// the number of bytes read and, for connectionless sockets,  the socket
 /// address of the sender.
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
 pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
     -> Result<(usize, Option<SockAddr>)>
 {
@@ -1549,7 +1581,7 @@
 
 /// Send a message to a socket
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
+/// [Further reading](https://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();
@@ -1561,7 +1593,7 @@
 
 /// Send data to a connection-oriented socket. Returns the number of bytes read
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
 pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
     let ret = unsafe {
         libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
@@ -1596,14 +1628,14 @@
 
 /// Get the current value for the requested socket option
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
 pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
     opt.get(fd)
 }
 
 /// Sets the value for the requested socket option
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
 ///
 /// # Examples
 ///
@@ -1624,7 +1656,7 @@
 
 /// Get the address of the peer connected to the socket `fd`.
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
 pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
     unsafe {
         let mut addr = mem::MaybeUninit::uninit();
@@ -1644,7 +1676,7 @@
 
 /// Get the current address to which the socket `fd` is bound.
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
 pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
     unsafe {
         let mut addr = mem::MaybeUninit::uninit();
@@ -1704,7 +1736,10 @@
         #[cfg(any(target_os = "android", target_os = "linux"))]
         libc::AF_PACKET => {
             use libc::sockaddr_ll;
-            assert_eq!(len as usize, mem::size_of::<sockaddr_ll>());
+            // 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!(len as usize <= mem::size_of::<sockaddr_ll>());
             let sll = unsafe {
                 *(addr as *const _ as *const sockaddr_ll)
             };
@@ -1751,7 +1786,7 @@
 
 /// Shut down part of a full-duplex connection.
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
+/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
 pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
     unsafe {
         use libc::shutdown;
@@ -1765,3 +1800,11 @@
         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 5b7b4fe..fe17395 100644
--- a/src/sys/socket/sockopt.rs
+++ b/src/sys/socket/sockopt.rs
@@ -214,6 +214,7 @@
  */
 
 sockopt_impl!(Both, ReuseAddr, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool);
+#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
 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);
@@ -225,10 +226,12 @@
         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 = "openbsd",
+                        target_os = "solaris"))] {
         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);
     }
@@ -269,6 +272,8 @@
 #[cfg(any(target_os = "android", target_os = "linux"))]
 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(all(target_os = "linux"))]
+sockopt_impl!(Both, ReceiveTimestampns, libc::SOL_SOCKET, libc::SO_TIMESTAMPNS, bool);
 #[cfg(any(target_os = "android", target_os = "linux"))]
 sockopt_impl!(Both, IpTransparent, libc::SOL_IP, libc::IP_TRANSPARENT, bool);
 #[cfg(target_os = "openbsd")]
diff --git a/src/sys/stat.rs b/src/sys/stat.rs
index df81a2c..15451e7 100644
--- a/src/sys/stat.rs
+++ b/src/sys/stat.rs
@@ -127,7 +127,7 @@
 ///
 /// # References
 ///
-/// [fchmod(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
+/// [fchmod(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
 pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> {
     let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) };
 
@@ -156,7 +156,7 @@
 ///
 /// # References
 ///
-/// [fchmodat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
+/// [fchmodat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
 #[cfg(not(target_os = "redox"))]
 pub fn fchmodat<P: ?Sized + NixPath>(
     dirfd: Option<RawFd>,
@@ -190,7 +190,7 @@
 ///
 /// # References
 ///
-/// [utimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
+/// [utimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
 pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
     let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
     let res = path.with_nix_path(|cstr| unsafe {
@@ -209,7 +209,7 @@
 ///
 /// # References
 ///
-/// [lutimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
+/// [lutimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
 #[cfg(any(target_os = "linux",
           target_os = "haiku",
           target_os = "ios",
@@ -229,7 +229,7 @@
 ///
 /// # References
 ///
-/// [futimens(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
+/// [futimens(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
 #[inline]
 pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> {
     let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
@@ -260,7 +260,7 @@
 ///
 /// # References
 ///
-/// [utimensat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
+/// [utimensat(2)](https://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/statvfs.rs b/src/sys/statvfs.rs
index 9bea973..508fa8d 100644
--- a/src/sys/statvfs.rs
+++ b/src/sys/statvfs.rs
@@ -1,6 +1,6 @@
 //! Get filesystem statistics
 //!
-//! See [the man pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
+//! See [the man pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
 //! for more details.
 use std::mem;
 use std::os::unix::io::AsRawFd;
@@ -54,7 +54,7 @@
 
 /// Wrapper around the POSIX `statvfs` struct
 ///
-/// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
+/// For more information see the [`statvfs(3)` man pages](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
 #[repr(transparent)]
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub struct Statvfs(libc::statvfs);
diff --git a/src/sys/sysinfo.rs b/src/sys/sysinfo.rs
index 222a2fc..dc943c1 100644
--- a/src/sys/sysinfo.rs
+++ b/src/sys/sysinfo.rs
@@ -71,7 +71,7 @@
 
 /// Returns system information.
 ///
-/// [See `sysinfo(2)`](http://man7.org/linux/man-pages/man2/sysinfo.2.html).
+/// [See `sysinfo(2)`](https://man7.org/linux/man-pages/man2/sysinfo.2.html).
 pub fn sysinfo() -> Result<SysInfo> {
     let mut info = mem::MaybeUninit::uninit();
     let res = unsafe { libc::sysinfo(info.as_mut_ptr()) };
diff --git a/src/sys/termios.rs b/src/sys/termios.rs
index c30de80..8c3c1cf 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](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html) and
+//! [API documentation](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html) and
 //! then come back to understand how `nix` safely wraps it.
 //!
 //! It should be noted that this API incurs some runtime overhead above the base `libc` definitions.
@@ -299,11 +299,17 @@
                 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 = "netbsd",
+                  target_os = "solaris"))]
         B460800,
         #[cfg(any(target_os = "android", target_os = "linux"))]
         B500000,
@@ -311,8 +317,10 @@
         B576000,
         #[cfg(any(target_os = "android",
                   target_os = "freebsd",
+                  target_os = "illumos",
                   target_os = "linux",
-                  target_os = "netbsd"))]
+                  target_os = "netbsd",
+                  target_os = "solaris"))]
         B921600,
         #[cfg(any(target_os = "android", target_os = "linux"))]
         B1000000,
@@ -354,6 +362,8 @@
                   target_os = "linux",
                   target_os = "netbsd"))]
         use libc::{B460800, B921600};
+        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
+        use libc::{B153600, B307200, B460800, B921600};
 
         match s {
             B0 => Ok(BaudRate::B0),
@@ -398,11 +408,19 @@
                       target_os = "openbsd"))]
             B76800 => Ok(BaudRate::B76800),
             B115200 => Ok(BaudRate::B115200),
+            #[cfg(any(target_os = "illumos",
+                      target_os = "solaris"))]
+            B153600 => Ok(BaudRate::B153600),
             B230400 => Ok(BaudRate::B230400),
+            #[cfg(any(target_os = "illumos",
+                      target_os = "solaris"))]
+            B307200 => Ok(BaudRate::B307200),
             #[cfg(any(target_os = "android",
                       target_os = "freebsd",
+                      target_os = "illumos",
                       target_os = "linux",
-                      target_os = "netbsd"))]
+                      target_os = "netbsd",
+                      target_os = "solaris"))]
             B460800 => Ok(BaudRate::B460800),
             #[cfg(any(target_os = "android", target_os = "linux"))]
             B500000 => Ok(BaudRate::B500000),
@@ -410,8 +428,10 @@
             B576000 => Ok(BaudRate::B576000),
             #[cfg(any(target_os = "android",
                       target_os = "freebsd",
+                      target_os = "illumos",
                       target_os = "linux",
-                      target_os = "netbsd"))]
+                      target_os = "netbsd",
+                      target_os = "solaris"))]
             B921600 => Ok(BaudRate::B921600),
             #[cfg(any(target_os = "android", target_os = "linux"))]
             B1000000 => Ok(BaudRate::B1000000),
@@ -502,37 +522,46 @@
         VDISCARD,
         #[cfg(any(target_os = "dragonfly",
                 target_os = "freebsd",
+                target_os = "illumos",
                 target_os = "macos",
                 target_os = "netbsd",
-                target_os = "openbsd"))]
+                target_os = "openbsd",
+                target_os = "solaris"))]
         VDSUSP,
         VEOF,
         VEOL,
         VEOL2,
         VERASE,
-        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
+        #[cfg(any(target_os = "dragonfly",
+                  target_os = "freebsd",
+                  target_os = "illumos",
+                  target_os = "solaris"))]
         VERASE2,
         VINTR,
         VKILL,
         VLNEXT,
-        #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
+        #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
+                target_os = "illumos", target_os = "solaris")))]
         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 = "openbsd",
+                target_os = "solaris"))]
         VSTATUS,
         VSTOP,
         VSUSP,
         #[cfg(target_os = "linux")]
         VSWTC,
-        #[cfg(target_os = "haiku")]
+        #[cfg(any(target_os = "haiku", target_os = "illumos", target_os = "solaris"))]
         VSWTCH,
-        #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
+        #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"),
+                target_os = "illumos", target_os = "solaris")))]
         VTIME,
         VWERASE,
         #[cfg(target_os = "dragonfly")]
@@ -540,7 +569,8 @@
     }
 }
 
-#[cfg(all(target_os = "linux", target_arch = "sparc64"))]
+#[cfg(any(all(target_os = "linux", target_arch = "sparc64"),
+        target_os = "illumos", target_os = "solaris"))]
 impl SpecialCharacterIndices {
     pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF;
     pub const VTIME: SpecialCharacterIndices = SpecialCharacterIndices::VEOL;
@@ -876,7 +906,7 @@
                  target_os = "netbsd",
                  target_os = "openbsd"))] {
         /// Get input baud rate (see
-        /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
+        /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
         ///
         /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
         pub fn cfgetispeed(termios: &Termios) -> u32 {
@@ -885,7 +915,7 @@
         }
 
         /// Get output baud rate (see
-        /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
+        /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
         ///
         /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
         pub fn cfgetospeed(termios: &Termios) -> u32 {
@@ -894,7 +924,7 @@
         }
 
         /// Set input baud rate (see
-        /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
+        /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
         ///
         /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
         pub fn cfsetispeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
@@ -905,7 +935,7 @@
         }
 
         /// Set output baud rate (see
-        /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
+        /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
         ///
         /// `cfsetospeed()` sets the output baud rate in the given termios structure.
         pub fn cfsetospeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
@@ -930,7 +960,7 @@
         use std::convert::TryInto;
 
         /// Get input baud rate (see
-        /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
+        /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
         ///
         /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
         pub fn cfgetispeed(termios: &Termios) -> BaudRate {
@@ -939,7 +969,7 @@
         }
 
         /// Get output baud rate (see
-        /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
+        /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
         ///
         /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
         pub fn cfgetospeed(termios: &Termios) -> BaudRate {
@@ -948,7 +978,7 @@
         }
 
         /// Set input baud rate (see
-        /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
+        /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
         ///
         /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
         pub fn cfsetispeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
@@ -959,7 +989,7 @@
         }
 
         /// Set output baud rate (see
-        /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
+        /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
         ///
         /// `cfsetospeed()` sets the output baud rate in the given `Termios` structure.
         pub fn cfsetospeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
@@ -984,7 +1014,7 @@
 }
 
 /// Configures the port to something like the "raw" mode of the old Version 7 terminal driver (see
-/// [termios(3)](http://man7.org/linux/man-pages/man3/termios.3.html)).
+/// [termios(3)](https://man7.org/linux/man-pages/man3/termios.3.html)).
 ///
 /// `cfmakeraw()` configures the termios structure such that input is available character-by-
 /// character, echoing is disabled, and all special input and output processing is disabled. Note
@@ -1011,7 +1041,7 @@
 }
 
 /// Return the configuration of a port
-/// [tcgetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)).
+/// [tcgetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)).
 ///
 /// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying
 /// this structure *will not* reconfigure the port, instead the modifications should be done to
@@ -1027,7 +1057,7 @@
 }
 
 /// Set the configuration for a terminal (see
-/// [tcsetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)).
+/// [tcsetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)).
 ///
 /// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change
 /// takes affect at a time specified by `actions`. Note that this function may return success if
@@ -1038,13 +1068,13 @@
 }
 
 /// Block until all output data is written (see
-/// [tcdrain(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
+/// [tcdrain(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
 pub fn tcdrain(fd: RawFd) -> Result<()> {
     Errno::result(unsafe { libc::tcdrain(fd) }).map(drop)
 }
 
 /// Suspend or resume the transmission or reception of data (see
-/// [tcflow(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)).
+/// [tcflow(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)).
 ///
 /// `tcflow()` suspends of resumes the transmission or reception of data for the given port
 /// depending on the value of `action`.
@@ -1053,7 +1083,7 @@
 }
 
 /// Discard data in the output or input queue (see
-/// [tcflush(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)).
+/// [tcflush(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)).
 ///
 /// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both
 /// depending on the value of `action`.
@@ -1062,7 +1092,7 @@
 }
 
 /// Send a break for a specific duration (see
-/// [tcsendbreak(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)).
+/// [tcsendbreak(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)).
 ///
 /// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream
 /// of zero-valued bits for an implementation-defined duration.
@@ -1071,7 +1101,7 @@
 }
 
 /// Get the session controlled by the given terminal (see
-/// [tcgetsid(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
+/// [tcgetsid(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
 pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
     let res = unsafe { libc::tcgetsid(fd) };
 
diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs
index 4a24719..e42fffd 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)](http://man7.org/linux/man-pages/man2/timerfd_create.2.html).
+//! For more documentation, please read [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html).
 //!
 //! # Examples
 //!
@@ -56,7 +56,7 @@
 
 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)](http://man7.org/linux/man-pages/man2/timerfd_create.2.html).
+    /// details on each kind of clock, please refer to [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html).
     #[repr(i32)]
     pub enum ClockId {
         CLOCK_REALTIME,
diff --git a/src/sys/uio.rs b/src/sys/uio.rs
index 6533422..b8ae860 100644
--- a/src/sys/uio.rs
+++ b/src/sys/uio.rs
@@ -112,7 +112,7 @@
 ///
 /// This function is only available on Linux.
 ///
-/// [`process_vm_writev`(2)]: http://man7.org/linux/man-pages/man2/process_vm_writev.2.html
+/// [`process_vm_writev`(2)]: https://man7.org/linux/man-pages/man2/process_vm_writev.2.html
 /// [ptrace]: ../ptrace/index.html
 /// [`IoVec`]: struct.IoVec.html
 /// [`RemoteIoVec`]: struct.RemoteIoVec.html
@@ -147,7 +147,7 @@
 ///
 /// This function is only available on Linux.
 ///
-/// [`process_vm_readv`(2)]: http://man7.org/linux/man-pages/man2/process_vm_readv.2.html
+/// [`process_vm_readv`(2)]: https://man7.org/linux/man-pages/man2/process_vm_readv.2.html
 /// [`ptrace`]: ../ptrace/index.html
 /// [`IoVec`]: struct.IoVec.html
 /// [`RemoteIoVec`]: struct.RemoteIoVec.html
diff --git a/src/sys/wait.rs b/src/sys/wait.rs
index faf8543..6c5c0f0 100644
--- a/src/sys/wait.rs
+++ b/src/sys/wait.rs
@@ -81,14 +81,14 @@
     /// field is the `PTRACE_EVENT_*` value of the event.
     ///
     /// [`nix::sys::ptrace`]: ../ptrace/index.html
-    /// [`ptrace`(2)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
+    /// [`ptrace`(2)]: https://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)]: http://man7.org/linux/man-pages/man2/ptrace.2.html
+    /// [`ptrace`(2)]: https://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
diff --git a/src/time.rs b/src/time.rs
index e6c3f8d..f7da654 100644
--- a/src/time.rs
+++ b/src/time.rs
@@ -185,9 +185,9 @@
     pub const CLOCK_VIRTUAL: ClockId = ClockId(libc::CLOCK_VIRTUAL);
 }
 
-impl Into<clockid_t> for ClockId {
-    fn into(self) -> clockid_t {
-        self.as_raw()
+impl From<ClockId> for clockid_t {
+    fn from(clock_id: ClockId) -> Self {
+        clock_id.as_raw()
     }
 }
 
diff --git a/src/unistd.rs b/src/unistd.rs
index 7a4517e..d406efe 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -29,6 +29,9 @@
           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
@@ -38,7 +41,7 @@
 
 impl Uid {
     /// Creates `Uid` from raw `uid_t`.
-    pub fn from_raw(uid: uid_t) -> Self {
+    pub const fn from_raw(uid: uid_t) -> Self {
         Uid(uid)
     }
 
@@ -53,12 +56,12 @@
     }
 
     /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.)
-    pub fn is_root(self) -> bool {
-        self == ROOT
+    pub const fn is_root(self) -> bool {
+        self.0 == ROOT.0
     }
 
     /// Get the raw `uid_t` wrapped by `self`.
-    pub fn as_raw(self) -> uid_t {
+    pub const fn as_raw(self) -> uid_t {
         self.0
     }
 }
@@ -87,7 +90,7 @@
 
 impl Gid {
     /// Creates `Gid` from raw `gid_t`.
-    pub fn from_raw(gid: gid_t) -> Self {
+    pub const fn from_raw(gid: gid_t) -> Self {
         Gid(gid)
     }
 
@@ -102,7 +105,7 @@
     }
 
     /// Get the raw `gid_t` wrapped by `self`.
-    pub fn as_raw(self) -> gid_t {
+    pub const fn as_raw(self) -> gid_t {
         self.0
     }
 }
@@ -128,7 +131,7 @@
 
 impl Pid {
     /// Creates `Pid` from raw `pid_t`.
-    pub fn from_raw(pid: pid_t) -> Self {
+    pub const fn from_raw(pid: pid_t) -> Self {
         Pid(pid)
     }
 
@@ -143,7 +146,7 @@
     }
 
     /// Get the raw `pid_t` wrapped by `self`.
-    pub fn as_raw(self) -> pid_t {
+    pub const fn as_raw(self) -> pid_t {
         self.0
     }
 }
@@ -191,7 +194,7 @@
 }
 
 /// Create a new child process duplicating the parent process ([see
-/// fork(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)).
+/// fork(2)](https://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
@@ -228,7 +231,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]: http://man7.org/linux/man-pages/man7/signal-safety.7.html
+/// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html
 #[inline]
 pub unsafe fn fork() -> Result<ForkResult> {
     use self::ForkResult::*;
@@ -241,7 +244,7 @@
 }
 
 /// Get the pid of this process (see
-/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)).
+/// [getpid(2)](https://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.
@@ -251,7 +254,7 @@
 }
 
 /// Get the pid of this processes' parent (see
-/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)).
+/// [getpid(2)](https://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.
@@ -261,7 +264,7 @@
 }
 
 /// Set a process group ID (see
-/// [setpgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)).
+/// [setpgid(2)](https://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
@@ -281,14 +284,14 @@
 }
 
 /// Create new session and set process group id (see
-/// [setsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)).
+/// [setsid(2)](https://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)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html).
+/// [getsid(2)](https://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.
@@ -301,7 +304,7 @@
 
 
 /// Get the terminal foreground process group (see
-/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)).
+/// [tcgetpgrp(3)](https://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).
@@ -311,7 +314,7 @@
     Errno::result(res).map(Pid)
 }
 /// Set the terminal foreground process group (see
-/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)).
+/// [tcgetpgrp(3)](https://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).
@@ -323,7 +326,7 @@
 
 
 /// Get the group id of the calling process (see
-///[getpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)).
+///[getpgrp(3)](https://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.
@@ -333,7 +336,7 @@
 }
 
 /// Get the caller's thread ID (see
-/// [gettid(2)](http://man7.org/linux/man-pages/man2/gettid.2.html).
+/// [gettid(2)](https://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
@@ -349,7 +352,7 @@
 }
 
 /// Create a copy of the specified file descriptor (see
-/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
+/// [dup(2)](https://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
@@ -366,7 +369,7 @@
 }
 
 /// Create a copy of the specified file descriptor using the specified fd (see
-/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
+/// [dup(2)](https://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
@@ -379,7 +382,7 @@
 }
 
 /// Create a new copy of the specified file descriptor using the specified fd
-/// and flags (see [dup(2)](http://man7.org/linux/man-pages/man2/dup.2.html)).
+/// and flags (see [dup(2)](https://man7.org/linux/man-pages/man2/dup.2.html)).
 ///
 /// This function behaves similar to `dup2()` but allows for flags to be
 /// specified.
@@ -406,7 +409,7 @@
 }
 
 /// Change the current working directory of the calling process (see
-/// [chdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)).
+/// [chdir(2)](https://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.
@@ -421,7 +424,7 @@
 
 /// Change the current working directory of the process to the one
 /// given as an open file descriptor (see
-/// [fchdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html)).
+/// [fchdir(2)](https://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.
@@ -433,7 +436,7 @@
     Errno::result(res).map(drop)
 }
 
-/// Creates new directory `path` with access rights `mode`.  (see [mkdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html))
+/// Creates new directory `path` with access rights `mode`.  (see [mkdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html))
 ///
 /// # Errors
 ///
@@ -450,15 +453,13 @@
 /// use nix::sys::stat;
 /// use tempfile::tempdir;
 ///
-/// fn main() {
-///     let tmp_dir1 = tempdir().unwrap();
-///     let tmp_dir2 = tmp_dir1.path().join("new_dir");
+/// 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]
@@ -481,7 +482,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](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html)
+/// [posix specification](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html)
 ///
 /// # Example
 ///
@@ -490,15 +491,13 @@
 /// use nix::sys::stat;
 /// use tempfile::tempdir;
 ///
-/// fn main() {
-///     let tmp_dir = tempdir().unwrap();
-///     let fifo_path = tmp_dir.path().join("foo.pipe");
+/// 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]
@@ -519,7 +518,7 @@
 ///
 /// # References
 ///
-/// [mkfifoat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html).
+/// [mkfifoat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html).
 // mkfifoat is not implemented in OSX or android
 #[inline]
 #[cfg(not(any(
@@ -541,7 +540,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)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
+/// See also [symlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
 #[cfg(not(target_os = "redox"))]
 pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
     path1: &P1,
@@ -587,11 +586,9 @@
 /// ```rust
 /// use nix::unistd;
 ///
-/// fn main() {
-///     // assume that we are allowed to get current directory
-///     let dir = unistd::getcwd().unwrap();
-///     println!("The current directory is {:?}", dir);
-/// }
+/// // 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> {
@@ -624,6 +621,8 @@
 }
 
 /// 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
@@ -637,7 +636,7 @@
 
 /// Change the ownership of the file at `path` to be owned by the specified
 /// `owner` (user) and `group` (see
-/// [chown(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html)).
+/// [chown(2)](https://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
@@ -693,7 +692,7 @@
 ///
 /// # References
 ///
-/// [fchownat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
+/// [fchownat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
 #[cfg(not(target_os = "redox"))]
 pub fn fchownat<P: ?Sized + NixPath>(
     dirfd: Option<RawFd>,
@@ -722,7 +721,7 @@
 }
 
 /// Replace the current process image with a new one (see
-/// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
+/// [exec(3)](https://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
@@ -740,7 +739,7 @@
 
 
 /// Replace the current process image with a new one (see
-/// [execve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
+/// [execve(2)](https://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
@@ -765,7 +764,7 @@
 
 /// Replace the current process image with a new one and replicate shell `PATH`
 /// searching behavior (see
-/// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
+/// [exec(3)](https://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
@@ -785,7 +784,7 @@
 
 /// Replace the current process image with a new one and replicate shell `PATH`
 /// searching behavior (see
-/// [`execvpe(3)`](http://man7.org/linux/man-pages/man3/exec.3.html)).
+/// [`execvpe(3)`](https://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
@@ -805,7 +804,7 @@
 }
 
 /// Replace the current process image with a new one (see
-/// [fexecve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)).
+/// [fexecve(2)](https://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
@@ -833,7 +832,7 @@
 }
 
 /// Execute program relative to a directory file descriptor (see
-/// [execveat(2)](http://man7.org/linux/man-pages/man2/execveat.2.html)).
+/// [execveat(2)](https://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
@@ -858,7 +857,7 @@
 }
 
 /// Daemonize this process by detaching from the controlling terminal (see
-/// [daemon(3)](http://man7.org/linux/man-pages/man3/daemon.3.html)).
+/// [daemon(3)](https://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
@@ -885,16 +884,18 @@
 #[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 = "openbsd",
+          target_os = "solaris"))]
 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)](http://man7.org/linux/man-pages/man2/gethostname.2.html)).
+/// [sethostname(2)](https://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
@@ -906,8 +907,10 @@
     cfg_if! {
         if #[cfg(any(target_os = "dragonfly",
                      target_os = "freebsd",
+                     target_os = "illumos",
                      target_os = "ios",
-                     target_os = "macos", ))] {
+                     target_os = "macos",
+                     target_os = "solaris", ))] {
             type sethostname_len_t = c_int;
         } else {
             type sethostname_len_t = size_t;
@@ -922,7 +925,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)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html)).
+/// [gethostname(2)](https://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
@@ -957,7 +960,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)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html).
+/// [close(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html).
 ///
 /// # Examples
 ///
@@ -965,20 +968,16 @@
 /// use std::os::unix::io::AsRawFd;
 /// use nix::unistd::close;
 ///
-/// fn main() {
-///     let f = tempfile::tempfile().unwrap();
-///     close(f.as_raw_fd()).unwrap();   // Bad!  f will also close on drop!
-/// }
+/// 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;
 ///
-/// fn main() {
-///     let f = tempfile::tempfile().unwrap();
-///     close(f.into_raw_fd()).unwrap(); // Good.  into_raw_fd consumes f
-/// }
+/// 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) };
@@ -987,7 +986,7 @@
 
 /// Read from a raw file descriptor.
 ///
-/// See also [read(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html)
+/// See also [read(2)](https://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) };
 
@@ -996,7 +995,7 @@
 
 /// Write to a raw file descriptor.
 ///
-/// See also [write(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
+/// See also [write(2)](https://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) };
 
@@ -1019,20 +1018,28 @@
     /// 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 = "linux"))]
+    #[cfg(any(target_os = "dragonfly",
+              target_os = "freebsd",
+              target_os = "illumos",
+              target_os = "linux",
+              target_os = "solaris"))]
     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 = "linux"))]
+    #[cfg(any(target_os = "dragonfly",
+              target_os = "freebsd",
+              target_os = "illumos",
+              target_os = "linux",
+              target_os = "solaris"))]
     SeekHole = libc::SEEK_HOLE
 }
 
 /// Move the read/write file offset.
 ///
-/// See also [lseek(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html)
+/// See also [lseek(2)](https://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) };
 
@@ -1048,7 +1055,7 @@
 
 /// Create an interprocess channel.
 ///
-/// See also [pipe(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
+/// See also [pipe(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
 pub fn pipe() -> Result<(RawFd, RawFd)> {
     unsafe {
         let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
@@ -1066,20 +1073,22 @@
 /// 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.  
+/// `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)](http://man7.org/linux/man-pages/man2/pipe.2.html)
+/// See also [pipe(2)](https://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 = "openbsd",
+          target_os = "solaris"))]
 pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
     let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
 
@@ -1095,7 +1104,7 @@
 /// Truncate a file to a specified length
 ///
 /// See also
-/// [truncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
+/// [truncate(2)](https://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| {
@@ -1110,7 +1119,7 @@
 /// Truncate a file to a specified length
 ///
 /// See also
-/// [ftruncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html)
+/// [ftruncate(2)](https://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)
 }
@@ -1149,7 +1158,7 @@
 /// process. If either `oldpath` or `newpath` is absolute, then `dirfd` is ignored.
 ///
 /// # References
-/// See also [linkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html)
+/// See also [linkat(2)](https://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>,
@@ -1185,7 +1194,7 @@
 
 /// Remove a directory entry
 ///
-/// See also [unlink(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
+/// See also [unlink(2)](https://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 {
@@ -1211,7 +1220,7 @@
 /// is performed.
 ///
 /// # References
-/// See also [unlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
+/// See also [unlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
 #[cfg(not(target_os = "redox"))]
 pub fn unlinkat<P: ?Sized + NixPath>(
     dirfd: Option<RawFd>,
@@ -1244,7 +1253,7 @@
 
 /// Commit filesystem caches to disk
 ///
-/// See also [sync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
+/// See also [sync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
 #[cfg(any(
     target_os = "dragonfly",
     target_os = "freebsd",
@@ -1258,7 +1267,7 @@
 
 /// Synchronize changes to a file
 ///
-/// See also [fsync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
+/// See also [fsync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
 #[inline]
 pub fn fsync(fd: RawFd) -> Result<()> {
     let res = unsafe { libc::fsync(fd) };
@@ -1269,12 +1278,14 @@
 /// Synchronize the data of a file
 ///
 /// See also
-/// [fdatasync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html)
+/// [fdatasync(2)](https://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 = "emscripten",
+          target_os = "illumos",
+          target_os = "solaris"))]
 #[inline]
 pub fn fdatasync(fd: RawFd) -> Result<()> {
     let res = unsafe { libc::fdatasync(fd) };
@@ -1284,7 +1295,7 @@
 
 /// Get a real user ID
 ///
-/// See also [getuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html)
+/// See also [getuid(2)](https://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]
@@ -1294,7 +1305,7 @@
 
 /// Get the effective user ID
 ///
-/// See also [geteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html)
+/// See also [geteuid(2)](https://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]
@@ -1304,7 +1315,7 @@
 
 /// Get the real group ID
 ///
-/// See also [getgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html)
+/// See also [getgid(2)](https://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]
@@ -1314,7 +1325,7 @@
 
 /// Get the effective group ID
 ///
-/// See also [getegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html)
+/// See also [getegid(2)](https://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]
@@ -1324,7 +1335,7 @@
 
 /// Set the effective user ID
 ///
-/// See also [seteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html)
+/// See also [seteuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html)
 #[inline]
 pub fn seteuid(euid: Uid) -> Result<()> {
     let res = unsafe { libc::seteuid(euid.into()) };
@@ -1334,7 +1345,7 @@
 
 /// Set the effective group ID
 ///
-/// See also [setegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html)
+/// See also [setegid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html)
 #[inline]
 pub fn setegid(egid: Gid) -> Result<()> {
     let res = unsafe { libc::setegid(egid.into()) };
@@ -1344,7 +1355,7 @@
 
 /// Set the user ID
 ///
-/// See also [setuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html)
+/// See also [setuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html)
 #[inline]
 pub fn setuid(uid: Uid) -> Result<()> {
     let res = unsafe { libc::setuid(uid.into()) };
@@ -1354,7 +1365,7 @@
 
 /// Set the group ID
 ///
-/// See also [setgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html)
+/// See also [setgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html)
 #[inline]
 pub fn setgid(gid: Gid) -> Result<()> {
     let res = unsafe { libc::setgid(gid.into()) };
@@ -1366,7 +1377,7 @@
 /// On both success and failure, this call returns the previous filesystem user
 /// ID of the caller.
 ///
-/// See also [setfsuid(2)](http://man7.org/linux/man-pages/man2/setfsuid.2.html)
+/// See also [setfsuid(2)](https://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()) };
@@ -1377,7 +1388,7 @@
 /// On both success and failure, this call returns the previous filesystem group
 /// ID of the caller.
 ///
-/// See also [setfsgid(2)](http://man7.org/linux/man-pages/man2/setfsgid.2.html)
+/// See also [setfsgid(2)](https://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()) };
@@ -1386,7 +1397,7 @@
 
 /// Get the list of supplementary group IDs of the calling process.
 ///
-/// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
+/// [Further reading](https://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
@@ -1434,7 +1445,7 @@
 
 /// Set the list of supplementary group IDs for the calling process.
 ///
-/// [Further reading](http://man7.org/linux/man-pages/man2/getgroups.2.html)
+/// [Further reading](https://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
@@ -1468,9 +1479,11 @@
     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 {
@@ -1492,7 +1505,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](http://man7.org/linux/man-pages/man3/getgrouplist.3.html)
+/// [Further reading](https://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
@@ -1507,7 +1520,10 @@
 /// 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 = "ios", target_os = "macos", target_os = "redox")))]
+#[cfg(not(any(target_os = "illumos",
+              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,
@@ -1542,7 +1558,7 @@
             // groups as possible, but Linux manpages do not mention this
             // behavior.
             reserve_double_buffer_size(&mut groups, ngroups_max as usize)
-                .or_else(|_| Err(Error::invalid_argument()))?;
+                .map_err(|_| Error::invalid_argument())?;
         }
     }
 }
@@ -1553,7 +1569,7 @@
 /// that `user` is a member of. The additional group `group` is also added to
 /// the list.
 ///
-/// [Further reading](http://man7.org/linux/man-pages/man3/initgroups.3.html)
+/// [Further reading](https://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
@@ -1602,7 +1618,7 @@
 
 /// Suspend the thread until a signal is received.
 ///
-/// See also [pause(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
+/// See also [pause(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
 #[inline]
 #[cfg(not(target_os = "redox"))]
 pub fn pause() {
@@ -1647,7 +1663,7 @@
     //! extern fn signal_handler(_: nix::libc::c_int) { }
     //! let sa = SigAction::new(
     //!     SigHandler::Handler(signal_handler),
-    //!     SaFlags::empty(),
+    //!     SaFlags::SA_RESTART,
     //!     SigSet::empty()
     //! );
     //! unsafe {
@@ -1668,7 +1684,7 @@
     //!
     //! # References
     //!
-    //! See also [alarm(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
+    //! See also [alarm(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
 
     /// Schedule an alarm signal.
     ///
@@ -1698,7 +1714,7 @@
 
 /// Suspend execution for an interval of time
 ///
-/// See also [sleep(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
+/// See also [sleep(2)](https://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 {
@@ -1738,7 +1754,7 @@
 /// Err is returned either if no temporary filename could be created or the template doesn't
 /// end with XXXXXX
 ///
-/// See also [mkstemp(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html)
+/// See also [mkstemp(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html)
 ///
 /// # Example
 ///
@@ -1769,7 +1785,7 @@
 /// Variable names for `pathconf`
 ///
 /// Nix uses the same naming convention for these variables as the
-/// [getconf(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
+/// [getconf(1)](https://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_`.
@@ -1779,9 +1795,9 @@
 ///
 /// # References
 ///
-/// - [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)
+/// - [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)
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 #[repr(i32)]
 pub enum PathconfVar {
@@ -1809,8 +1825,9 @@
     /// 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 = "linux",
-              target_os = "netbsd", target_os = "openbsd", target_os = "redox"))]
+    #[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"))]
     /// Symbolic links can be created.
     POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
@@ -1836,8 +1853,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 = "linux", target_os = "netbsd", target_os = "openbsd",
-              target_os = "redox"))]
+              target_os = "illumos", target_os = "linux", target_os = "netbsd",
+              target_os = "openbsd", target_os = "redox", target_os = "solaris"))]
     /// 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
@@ -1851,18 +1868,20 @@
     /// disable terminal special character handling.
     _POSIX_VDISABLE = libc::_PC_VDISABLE,
     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
+              target_os = "illumos", target_os = "linux", target_os = "openbsd",
+              target_os = "redox", target_os = "solaris"))]
     /// 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 = "linux", target_os = "openbsd", target_os = "redox"))]
+              target_os = "illumos", target_os = "linux", target_os = "openbsd",
+              target_os = "redox", target_os = "solaris"))]
     /// 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 = "linux", target_os = "netbsd", target_os = "openbsd",
-              target_os = "redox"))]
+              target_os = "illumos", target_os = "linux", target_os = "netbsd",
+              target_os = "openbsd", target_os = "redox", target_os = "solaris"))]
     /// Synchronized input or output operations may be performed for the
     /// associated file.
     _POSIX_SYNC_IO = libc::_PC_SYNC_IO,
@@ -1872,7 +1891,7 @@
 }
 
 /// Like `pathconf`, but works with file descriptors instead of paths (see
-/// [fpathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
+/// [fpathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
 ///
 /// # Parameters
 ///
@@ -1904,12 +1923,12 @@
 }
 
 /// Get path-dependent configurable system variables (see
-/// [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
+/// [pathconf(2)](https://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)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details.
+/// `pathconf` variables: options and limits.  See [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details.
 ///
 /// # Parameters
 ///
@@ -1945,7 +1964,7 @@
 /// Variable names for `sysconf`
 ///
 /// Nix uses the same naming convention for these variables as the
-/// [getconf(1)](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility.
+/// [getconf(1)](https://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_`.
@@ -1955,9 +1974,9 @@
 ///
 /// # References
 ///
-/// - [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)
+/// - [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)
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 #[repr(i32)]
 pub enum SysconfVar {
@@ -2007,9 +2026,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 = "ios",
-              target_os="linux", target_os = "macos", target_os="netbsd",
-              target_os="openbsd"))]
+    #[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"))]
     /// 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,
@@ -2046,29 +2065,30 @@
               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 = "ios",
-              target_os="linux", target_os = "macos", target_os="netbsd",
-              target_os="openbsd"))]
+    #[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"))]
     /// 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 = "ios",
-              target_os="linux", target_os = "macos", target_os="netbsd",
-              target_os="openbsd"))]
+    #[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"))]
     /// The implementation supports clock selection.
     _POSIX_CLOCK_SELECTION = libc::_SC_CLOCK_SELECTION,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-              target_os="linux", target_os = "macos", target_os="netbsd",
-              target_os="openbsd"))]
+    #[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"))]
     /// 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 = "ios",
-              target_os="linux", target_os = "macos", target_os="openbsd"))]
+    #[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"))]
     /// The implementation supports the IPv6 option.
     _POSIX_IPV6 = libc::_SC_IPV6,
     /// The implementation supports job control.
@@ -2093,20 +2113,21 @@
     #[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 = "ios", target_os="linux", target_os = "macos",
-              target_os="openbsd"))]
+              target_os = "illumos", target_os = "ios", target_os="linux",
+              target_os = "macos", target_os="openbsd", target_os = "solaris"))]
     /// 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 = "ios",
-              target_os="linux", target_os = "macos", target_os="openbsd"))]
+    #[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"))]
     /// The implementation supports the Raw Sockets option.
     _POSIX_RAW_SOCKETS = libc::_SC_RAW_SOCKETS,
-    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-              target_os="linux", target_os = "macos", target_os="netbsd",
-              target_os="openbsd"))]
+    #[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"))]
     /// 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",
@@ -2114,9 +2135,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 = "ios",
-              target_os="linux", target_os = "macos", target_os="netbsd",
-              target_os="openbsd"))]
+    #[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"))]
     /// 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.
@@ -2408,7 +2429,7 @@
 }
 
 /// Get configurable system variables (see
-/// [sysconf(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html))
+/// [sysconf(3)](https://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 +2487,7 @@
     use super::{Uid, Gid};
 
     /// Sets the real, effective, and saved uid.
-    /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
+    /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html))
     ///
     /// * `ruid`: real user id
     /// * `euid`: effective user id
@@ -2482,7 +2503,7 @@
     }
 
     /// Sets the real, effective, and saved gid.
-    /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
+    /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html))
     ///
     /// * `rgid`: real group id
     /// * `egid`: effective group id
@@ -2498,6 +2519,67 @@
     }
 }
 
+#[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 {
@@ -2513,7 +2595,7 @@
 }
 
 /// Checks the file named by `path` for accessibility according to the flags given by `amode`
-/// See [access(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html)
+/// See [access(2)](https://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 {
@@ -2548,16 +2630,25 @@
     /// Path to shell
     pub shell: PathBuf,
     /// Login class
-    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-                  target_os = "linux")))]
+    #[cfg(not(any(target_os = "android",
+                  target_os = "fuchsia",
+                  target_os = "illumos",
+                  target_os = "linux",
+                  target_os = "solaris")))]
     pub class: CString,
     /// Last password change
-    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-                  target_os = "linux")))]
+    #[cfg(not(any(target_os = "android",
+                  target_os = "fuchsia",
+                  target_os = "illumos",
+                  target_os = "linux",
+                  target_os = "solaris")))]
     pub change: libc::time_t,
     /// Expiration time of account
-    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-                  target_os = "linux")))]
+    #[cfg(not(any(target_os = "android",
+                  target_os = "fuchsia",
+                  target_os = "illumos",
+                  target_os = "linux",
+                  target_os = "solaris")))]
     pub expire: libc::time_t
 }
 
@@ -2574,14 +2665,23 @@
                 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 = "linux")))]
+                #[cfg(not(any(target_os = "android",
+                              target_os = "fuchsia",
+                              target_os = "illumos",
+                              target_os = "linux",
+                              target_os = "solaris")))]
                 class: CString::new(CStr::from_ptr((*pw).pw_class).to_bytes()).unwrap(),
-                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-                              target_os = "linux")))]
+                #[cfg(not(any(target_os = "android",
+                              target_os = "fuchsia",
+                              target_os = "illumos",
+                              target_os = "linux",
+                              target_os = "solaris")))]
                 change: (*pw).pw_change,
-                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-                              target_os = "linux")))]
+                #[cfg(not(any(target_os = "android",
+                              target_os = "fuchsia",
+                              target_os = "illumos",
+                              target_os = "linux",
+                              target_os = "solaris")))]
                 expire: (*pw).pw_expire
             }
         }
@@ -2597,10 +2697,10 @@
               libc::size_t,
               *mut *mut libc::passwd) -> libc::c_int
     {
-        let buflimit = 16384;
+        let buflimit = 1048576;
         let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) {
             Ok(Some(n)) => n as usize,
-            Ok(None) | Err(_) => buflimit as usize,
+            Ok(None) | Err(_) => 16384,
         };
 
         let mut cbuf = Vec::with_capacity(bufsize);
@@ -2628,7 +2728,7 @@
     /// Get a user by UID.
     ///
     /// Internally, this function calls
-    /// [getpwuid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
+    /// [getpwuid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
     ///
     /// # Examples
     ///
@@ -2647,7 +2747,7 @@
     /// Get a user by name.
     ///
     /// Internally, this function calls
-    /// [getpwnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
+    /// [getpwnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
     ///
     /// # Examples
     ///
@@ -2718,10 +2818,10 @@
               libc::size_t,
               *mut *mut libc::group) -> libc::c_int
     {
-        let buflimit = 16384;
+        let buflimit = 1048576;
         let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) {
             Ok(Some(n)) => n as usize,
-            Ok(None) | Err(_) => buflimit as usize,
+            Ok(None) | Err(_) => 16384,
         };
 
         let mut cbuf = Vec::with_capacity(bufsize);
@@ -2749,7 +2849,7 @@
     /// Get a group by GID.
     ///
     /// Internally, this function calls
-    /// [getgrgid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
+    /// [getgrgid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
     ///
     /// # Examples
     ///
@@ -2770,7 +2870,7 @@
     /// Get a group by name.
     ///
     /// Internally, this function calls
-    /// [getgrnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
+    /// [getgrnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
     ///
     /// # Examples
     ///
@@ -2791,7 +2891,7 @@
 }
 
 /// Get the name of the terminal device that is open on file descriptor fd
-/// (see [`ttyname(3)`](http://man7.org/linux/man-pages/man3/ttyname.3.html)).
+/// (see [`ttyname(3)`](https://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;