diff --git a/src/unix/mod.rs b/src/unix/mod.rs
index 8295dfc020c9c664b761eb1c83a8492179395de0..65cf7ecf5c05ddce63bc4ead31ab1da3065a342e 100644
--- a/src/unix/mod.rs
+++ b/src/unix/mod.rs
@@ -605,12 +605,6 @@ extern {
     #[cfg_attr(target_os = "netbsd", link_name = "__opendir30")]
     pub fn opendir(dirname: *const c_char) -> *mut ::DIR;
 
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"),
-               link_name = "fdopendir$INODE64")]
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "fdopendir$INODE64$UNIX2003")]
-    pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
-
     #[cfg_attr(target_os = "macos", link_name = "readdir$INODE64")]
     #[cfg_attr(target_os = "netbsd", link_name = "__readdir30")]
     #[cfg_attr(
@@ -618,20 +612,6 @@ extern {
         link_name = "readdir@FBSD_1.0"
     )]
     pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent;
-    #[cfg_attr(target_os = "macos", link_name = "readdir_r$INODE64")]
-    #[cfg_attr(target_os = "netbsd", link_name = "__readdir_r30")]
-    #[cfg_attr(
-        all(target_os = "freebsd", not(freebsd12)),
-        link_name = "readdir_r@FBSD_1.0"
-    )]
-    /// The 64-bit libc on Solaris and illumos only has readdir_r.  If a
-    /// 32-bit Solaris or illumos target is ever created, it should use
-    /// __posix_readdir_r.  See libc(3LIB) on Solaris or illumos:
-    /// https://illumos.org/man/3lib/libc
-    /// https://docs.oracle.com/cd/E36784_01/html/E36873/libc-3lib.html
-    /// https://www.unix.com/man-page/opensolaris/3LIB/libc/
-    pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent,
-                     result: *mut *mut ::dirent) -> ::c_int;
     #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
                link_name = "closedir$UNIX2003")]
     pub fn closedir(dirp: *mut ::DIR) -> ::c_int;
@@ -641,8 +621,6 @@ extern {
                link_name = "rewinddir$INODE64$UNIX2003")]
     pub fn rewinddir(dirp: *mut ::DIR);
 
-    pub fn openat(dirfd: ::c_int, pathname: *const ::c_char,
-                  flags: ::c_int, ...) -> ::c_int;
     pub fn fchmodat(dirfd: ::c_int, pathname: *const ::c_char,
                     mode: ::mode_t, flags: ::c_int) -> ::c_int;
     pub fn fchown(fd: ::c_int,
@@ -661,10 +639,6 @@ extern {
     pub fn linkat(olddirfd: ::c_int, oldpath: *const ::c_char,
                   newdirfd: ::c_int, newpath: *const ::c_char,
                   flags: ::c_int) -> ::c_int;
-    pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char,
-                   mode: ::mode_t) -> ::c_int;
-    pub fn readlinkat(dirfd: ::c_int, pathname: *const ::c_char,
-                      buf: *mut ::c_char, bufsiz: ::size_t) -> ::ssize_t;
     pub fn renameat(olddirfd: ::c_int, oldpath: *const ::c_char,
                     newdirfd: ::c_int, newpath: *const ::c_char)
                     -> ::c_int;
@@ -725,9 +699,6 @@ extern {
     pub fn link(src: *const c_char, dst: *const c_char) -> ::c_int;
     pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t;
     pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long;
-    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
-               link_name = "pause$UNIX2003")]
-    pub fn pause() -> ::c_int;
     pub fn pipe(fds: *mut ::c_int) -> ::c_int;
     pub fn posix_memalign(memptr: *mut *mut ::c_void,
                       align: ::size_t,
@@ -836,7 +807,6 @@ extern {
     pub fn symlink(path1: *const c_char,
                    path2: *const c_char) -> ::c_int;
 
-    pub fn truncate(path: *const c_char, length: off_t) -> ::c_int;
     pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int;
 
     pub fn signal(signum: ::c_int, handler: sighandler_t) -> sighandler_t;
@@ -1071,8 +1041,6 @@ extern {
     #[cfg_attr(target_os = "netbsd", link_name = "__timegm50")]
     pub fn timegm(tm: *mut ::tm) -> time_t;
 
-    pub fn getsid(pid: pid_t) -> pid_t;
-
     pub fn sysconf(name: ::c_int) -> ::c_long;
 
     pub fn mkfifo(path: *const c_char, mode: mode_t) -> ::c_int;
@@ -1131,6 +1099,48 @@ extern {
         stream: *mut FILE) -> ssize_t;
 }
 
+cfg_if! {
+    if #[cfg(not(target_os = "redox"))] {
+        extern {
+            pub fn getsid(pid: pid_t) -> pid_t;
+            pub fn truncate(path: *const c_char, length: off_t) -> ::c_int;
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+                       link_name = "pause$UNIX2003")]
+            pub fn pause() -> ::c_int;
+
+            pub fn readlinkat(dirfd: ::c_int,
+                              pathname: *const ::c_char,
+                              buf: *mut ::c_char,
+                              bufsiz: ::size_t) -> ::ssize_t;
+            pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char,
+                           mode: ::mode_t) -> ::c_int;
+            pub fn openat(dirfd: ::c_int, pathname: *const ::c_char,
+                          flags: ::c_int, ...) -> ::c_int;
+
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"),
+                       link_name = "fdopendir$INODE64")]
+            #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+                       link_name = "fdopendir$INODE64$UNIX2003")]
+            pub fn fdopendir(fd: ::c_int) -> *mut ::DIR;
+
+            #[cfg_attr(target_os = "macos", link_name = "readdir_r$INODE64")]
+            #[cfg_attr(target_os = "netbsd", link_name = "__readdir_r30")]
+            #[cfg_attr(
+                all(target_os = "freebsd", not(freebsd12)),
+                link_name = "readdir_r@FBSD_1.0"
+            )]
+            /// The 64-bit libc on Solaris and illumos only has readdir_r.  If a
+            /// 32-bit Solaris or illumos target is ever created, it should use
+            /// __posix_readdir_r.  See libc(3LIB) on Solaris or illumos:
+            /// https://illumos.org/man/3lib/libc
+            /// https://docs.oracle.com/cd/E36784_01/html/E36873/libc-3lib.html
+            /// https://www.unix.com/man-page/opensolaris/3LIB/libc/
+            pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent,
+                             result: *mut *mut ::dirent) -> ::c_int;
+        }
+    }
+}
+
 cfg_if! {
    if #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] {
         extern {
diff --git a/src/unix/redox/mod.rs b/src/unix/redox/mod.rs
index 121bb63a6601f138b920a90f566ad432a4411ed2..2591a7938acbb5074d76af498e435fdc26ba9a74 100644
--- a/src/unix/redox/mod.rs
+++ b/src/unix/redox/mod.rs
@@ -36,6 +36,49 @@ pub type suseconds_t = ::c_int;
 pub type tcflag_t = u32;
 pub type time_t = ::c_long;
 
+#[cfg_attr(feature = "extra_traits", derive(Debug))]
+pub enum timezone {}
+impl ::Copy for timezone {}
+impl ::Clone for timezone {
+    fn clone(&self) -> timezone { *self }
+}
+
+s_no_extra_traits! {
+    #[repr(C)]
+    pub struct utsname {
+        pub sysname: [::c_char; UTSLENGTH],
+        pub nodename: [::c_char; UTSLENGTH],
+        pub release: [::c_char; UTSLENGTH],
+        pub version: [::c_char; UTSLENGTH],
+        pub machine: [::c_char; UTSLENGTH],
+        pub domainname: [::c_char; UTSLENGTH],
+    }
+
+    pub struct dirent {
+        pub d_ino: ::ino_t,
+        pub d_off: ::off_t,
+        pub d_reclen: ::c_ushort,
+        pub d_type: ::c_uchar,
+        pub d_name: [::c_char; 256],
+    }
+
+    pub struct sockaddr_un {
+        pub sun_family: ::sa_family_t,
+        pub sun_path: [::c_char; 108]
+    }
+
+    pub struct sockaddr_storage {
+        pub ss_family: ::sa_family_t,
+        __ss_padding: [
+            u8;
+            128 -
+            ::core::mem::size_of::<sa_family_t>() -
+            ::core::mem::size_of::<c_ulong>()
+        ],
+        __ss_align: ::c_ulong,
+    }
+}
+
 s! {
     pub struct addrinfo {
         pub ai_flags: ::c_int,
@@ -48,14 +91,6 @@ s! {
         pub ai_next: *mut ::addrinfo,
     }
 
-    pub struct dirent {
-        pub d_ino: ::ino_t,
-        pub d_off: ::off_t,
-        pub d_reclen: ::c_ushort,
-        pub d_type: ::c_uchar,
-        pub d_name: [::c_char; 256],
-    }
-
     pub struct Dl_info {
         pub dli_fname: *const ::c_char,
         pub dli_fbase: *mut ::c_void,
@@ -140,22 +175,6 @@ s! {
         pub sin6_scope_id: u32,
     }
 
-    pub struct sockaddr_storage {
-        pub ss_family: ::sa_family_t,
-        __ss_padding: [
-            u8;
-            128 -
-            ::core::mem::size_of::<sa_family_t>() -
-            ::core::mem::size_of::<c_ulong>()
-        ],
-        __ss_align: ::c_ulong,
-    }
-
-    pub struct sockaddr_un {
-        pub sun_family: ::sa_family_t,
-        pub sun_path: [::c_char; 108]
-    }
-
     pub struct stat {
         pub st_dev: ::dev_t,
         pub st_ino: ::ino_t,
@@ -216,63 +235,175 @@ s! {
     }
 }
 
+pub const UTSLENGTH: usize = 65;
+
+// intentionally not public, only used for fd_set
+cfg_if! {
+    if #[cfg(target_pointer_width = "32")] {
+        const ULONG_SIZE: usize = 32;
+    } else if #[cfg(target_pointer_width = "64")] {
+        const ULONG_SIZE: usize = 64;
+    } else {
+        // Unknown target_pointer_width
+    }
+}
+
+// limits.h
+pub const PATH_MAX: ::c_int = 4096;
+
+// fcntl.h
+pub const F_GETLK: ::c_int = 5;
+pub const F_SETLK: ::c_int = 6;
+pub const F_SETLKW: ::c_int = 7;
+
 // TODO: relibc {
-    pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void;
+pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void;
 // }
 
 // dlfcn.h
-
 pub const RTLD_LAZY: ::c_int = 0x0001;
 pub const RTLD_NOW: ::c_int = 0x0002;
 pub const RTLD_GLOBAL: ::c_int = 0x0100;
 pub const RTLD_LOCAL: ::c_int = 0x0000;
 
 // errno.h
-pub const EPERM: ::c_int = 1;
-pub const ENOENT: ::c_int = 2;
-pub const ESRCH: ::c_int = 3;
-pub const EINTR: ::c_int = 4;
-pub const EIO: ::c_int = 5;
-pub const ENXIO: ::c_int = 6;
-pub const E2BIG: ::c_int = 7;
-pub const ENOEXEC: ::c_int = 8;
-pub const EBADF: ::c_int = 9;
-pub const ECHILD: ::c_int = 10;
-pub const EAGAIN: ::c_int = 11;
-pub const ENOMEM: ::c_int = 12;
-pub const EACCES: ::c_int = 13;
-pub const EFAULT: ::c_int = 14;
-pub const ENOTBLK: ::c_int = 15;
-pub const EBUSY: ::c_int = 16;
-pub const EEXIST: ::c_int = 17;
-pub const EXDEV: ::c_int = 18;
-pub const ENODEV: ::c_int = 19;
-pub const ENOTDIR: ::c_int = 20;
-pub const EISDIR: ::c_int = 21;
-pub const EINVAL: ::c_int = 22;
-pub const ENFILE: ::c_int = 23;
-pub const EMFILE: ::c_int = 24;
-pub const ENOTTY: ::c_int = 25;
-pub const ETXTBSY: ::c_int = 26;
-pub const EFBIG: ::c_int = 27;
-pub const ENOSPC: ::c_int = 28;
-pub const ESPIPE: ::c_int = 29;
-pub const EROFS: ::c_int = 30;
-pub const EMLINK: ::c_int = 31;
-pub const EPIPE: ::c_int = 32;
-pub const EDOM: ::c_int = 33;
-pub const ERANGE: ::c_int = 34;
-pub const EDEADLK: ::c_int = 35;
-pub const ENOSYS: ::c_int = 38;
-pub const EWOULDBLOCK: ::c_int = 41;
-pub const EADDRINUSE: ::c_int = 98;
-pub const EADDRNOTAVAIL: ::c_int = 99;
-pub const ECONNABORTED: ::c_int = 103;
-pub const ECONNRESET: ::c_int = 104;
-pub const ENOTCONN: ::c_int = 107;
-pub const ETIMEDOUT: ::c_int = 110;
-pub const ECONNREFUSED: ::c_int = 111;
-pub const EINPROGRESS: ::c_int = 115;
+pub const EPERM: ::c_int = 1; /* Operation not permitted */
+pub const ENOENT: ::c_int = 2; /* No such file or directory */
+pub const ESRCH: ::c_int = 3; /* No such process */
+pub const EINTR: ::c_int = 4; /* Interrupted system call */
+pub const EIO: ::c_int = 5; /* I/O error */
+pub const ENXIO: ::c_int = 6; /* No such device or address */
+pub const E2BIG: ::c_int = 7; /* Argument list too long */
+pub const ENOEXEC: ::c_int = 8; /* Exec format error */
+pub const EBADF: ::c_int = 9; /* Bad file number */
+pub const ECHILD: ::c_int = 10; /* No child processes */
+pub const EAGAIN: ::c_int = 11; /* Try again */
+pub const ENOMEM: ::c_int = 12; /* Out of memory */
+pub const EACCES: ::c_int = 13; /* Permission denied */
+pub const EFAULT: ::c_int = 14; /* Bad address */
+pub const ENOTBLK: ::c_int = 15; /* Block device required */
+pub const EBUSY: ::c_int = 16; /* Device or resource busy */
+pub const EEXIST: ::c_int = 17; /* File exists */
+pub const EXDEV: ::c_int = 18; /* Cross-device link */
+pub const ENODEV: ::c_int = 19; /* No such device */
+pub const ENOTDIR: ::c_int = 20; /* Not a directory */
+pub const EISDIR: ::c_int = 21; /* Is a directory */
+pub const EINVAL: ::c_int = 22; /* Invalid argument */
+pub const ENFILE: ::c_int = 23; /* File table overflow */
+pub const EMFILE: ::c_int = 24; /* Too many open files */
+pub const ENOTTY: ::c_int = 25; /* Not a typewriter */
+pub const ETXTBSY: ::c_int = 26; /* Text file busy */
+pub const EFBIG: ::c_int = 27; /* File too large */
+pub const ENOSPC: ::c_int = 28; /* No space left on device */
+pub const ESPIPE: ::c_int = 29; /* Illegal seek */
+pub const EROFS: ::c_int = 30; /* Read-only file system */
+pub const EMLINK: ::c_int = 31; /* Too many links */
+pub const EPIPE: ::c_int = 32; /* Broken pipe */
+pub const EDOM: ::c_int = 33; /* Math argument out of domain of func */
+pub const ERANGE: ::c_int = 34; /* Math result not representable */
+pub const EDEADLK: ::c_int = 35; /* Resource deadlock would occur */
+pub const ENAMETOOLONG: ::c_int = 36; /* File name too long */
+pub const ENOLCK: ::c_int = 37; /* No record locks available */
+pub const ENOSYS: ::c_int = 38; /* Function not implemented */
+pub const ENOTEMPTY: ::c_int = 39; /* Directory not empty */
+pub const ELOOP: ::c_int = 40; /* Too many symbolic links encountered */
+pub const EWOULDBLOCK: ::c_int = 41; /* Operation would block */
+pub const ENOMSG: ::c_int = 42; /* No message of desired type */
+pub const EIDRM: ::c_int = 43; /* Identifier removed */
+pub const ECHRNG: ::c_int = 44; /* Channel number out of range */
+pub const EL2NSYNC: ::c_int = 45; /* Level 2 not synchronized */
+pub const EL3HLT: ::c_int = 46; /* Level 3 halted */
+pub const EL3RST: ::c_int = 47; /* Level 3 reset */
+pub const ELNRNG: ::c_int = 48; /* Link number out of range */
+pub const EUNATCH: ::c_int = 49; /* Protocol driver not attached */
+pub const ENOCSI: ::c_int = 50; /* No CSI structure available */
+pub const EL2HLT: ::c_int = 51; /* Level 2 halted */
+pub const EBADE: ::c_int = 52; /* Invalid exchange */
+pub const EBADR: ::c_int = 53; /* Invalid request descriptor */
+pub const EXFULL: ::c_int = 54; /* Exchange full */
+pub const ENOANO: ::c_int = 55; /* No anode */
+pub const EBADRQC: ::c_int = 56; /* Invalid request code */
+pub const EBADSLT: ::c_int = 57; /* Invalid slot */
+pub const EDEADLOCK: ::c_int = 58; /* Resource deadlock would occur */
+pub const EBFONT: ::c_int = 59; /* Bad font file format */
+pub const ENOSTR: ::c_int = 60; /* Device not a stream */
+pub const ENODATA: ::c_int = 61; /* No data available */
+pub const ETIME: ::c_int = 62; /* Timer expired */
+pub const ENOSR: ::c_int = 63; /* Out of streams resources */
+pub const ENONET: ::c_int = 64; /* Machine is not on the network */
+pub const ENOPKG: ::c_int = 65; /* Package not installed */
+pub const EREMOTE: ::c_int = 66; /* Object is remote */
+pub const ENOLINK: ::c_int = 67; /* Link has been severed */
+pub const EADV: ::c_int = 68; /* Advertise error */
+pub const ESRMNT: ::c_int = 69; /* Srmount error */
+pub const ECOMM: ::c_int = 70; /* Communication error on send */
+pub const EPROTO: ::c_int = 71; /* Protocol error */
+pub const EMULTIHOP: ::c_int = 72; /* Multihop attempted */
+pub const EDOTDOT: ::c_int = 73; /* RFS specific error */
+pub const EBADMSG: ::c_int = 74; /* Not a data message */
+pub const EOVERFLOW: ::c_int = 75; /* Value too large for defined data type */
+pub const ENOTUNIQ: ::c_int = 76; /* Name not unique on network */
+pub const EBADFD: ::c_int = 77; /* File descriptor in bad state */
+pub const EREMCHG: ::c_int = 78; /* Remote address changed */
+pub const ELIBACC: ::c_int = 79; /* Can not access a needed shared library */
+pub const ELIBBAD: ::c_int = 80; /* Accessing a corrupted shared library */
+pub const ELIBSCN: ::c_int = 81; /* .lib section in a.out corrupted */
+/* Attempting to link in too many shared libraries */
+pub const ELIBMAX: ::c_int = 82;
+pub const ELIBEXEC: ::c_int = 83; /* Cannot exec a shared library directly */
+pub const EILSEQ: ::c_int = 84; /* Illegal byte sequence */
+/* Interrupted system call should be restarted */
+pub const ERESTART: ::c_int = 85;
+pub const ESTRPIPE: ::c_int = 86; /* Streams pipe error */
+pub const EUSERS: ::c_int = 87; /* Too many users */
+pub const ENOTSOCK: ::c_int = 88; /* Socket operation on non-socket */
+pub const EDESTADDRREQ: ::c_int = 89; /* Destination address required */
+pub const EMSGSIZE: ::c_int = 90; /* Message too long */
+pub const EPROTOTYPE: ::c_int = 91; /* Protocol wrong type for socket */
+pub const ENOPROTOOPT: ::c_int = 92; /* Protocol not available */
+pub const EPROTONOSUPPORT: ::c_int = 93; /* Protocol not supported */
+pub const ESOCKTNOSUPPORT: ::c_int = 94; /* Socket type not supported */
+/* Operation not supported on transport endpoint */
+pub const EOPNOTSUPP: ::c_int = 95;
+pub const EPFNOSUPPORT: ::c_int = 96; /* Protocol family not supported */
+/* Address family not supported by protocol */
+pub const EAFNOSUPPORT: ::c_int = 97;
+pub const EADDRINUSE: ::c_int = 98; /* Address already in use */
+pub const EADDRNOTAVAIL: ::c_int = 99; /* Cannot assign requested address */
+pub const ENETDOWN: ::c_int = 100; /* Network is down */
+pub const ENETUNREACH: ::c_int = 101; /* Network is unreachable */
+/* Network dropped connection because of reset */
+pub const ENETRESET: ::c_int = 102;
+pub const ECONNABORTED: ::c_int = 103; /* Software caused connection abort */
+pub const ECONNRESET: ::c_int = 104; /* Connection reset by peer */
+pub const ENOBUFS: ::c_int = 105; /* No buffer space available */
+pub const EISCONN: ::c_int = 106; /* Transport endpoint is already connected */
+pub const ENOTCONN: ::c_int = 107; /* Transport endpoint is not connected */
+/* Cannot send after transport endpoint shutdown */
+pub const ESHUTDOWN: ::c_int = 108;
+pub const ETOOMANYREFS: ::c_int = 109; /* Too many references: cannot splice */
+pub const ETIMEDOUT: ::c_int = 110; /* Connection timed out */
+pub const ECONNREFUSED: ::c_int = 111; /* Connection refused */
+pub const EHOSTDOWN: ::c_int = 112; /* Host is down */
+pub const EHOSTUNREACH: ::c_int = 113; /* No route to host */
+pub const EALREADY: ::c_int = 114; /* Operation already in progress */
+pub const EINPROGRESS: ::c_int = 115; /* Operation now in progress */
+pub const ESTALE: ::c_int = 116; /* Stale NFS file handle */
+pub const EUCLEAN: ::c_int = 117; /* Structure needs cleaning */
+pub const ENOTNAM: ::c_int = 118; /* Not a XENIX named type file */
+pub const ENAVAIL: ::c_int = 119; /* No XENIX semaphores available */
+pub const EISNAM: ::c_int = 120; /* Is a named type file */
+pub const EREMOTEIO: ::c_int = 121; /* Remote I/O error */
+pub const EDQUOT: ::c_int = 122; /* Quota exceeded */
+pub const ENOMEDIUM: ::c_int = 123; /* No medium found */
+pub const EMEDIUMTYPE: ::c_int = 124; /* Wrong medium type */
+pub const ECANCELED: ::c_int = 125; /* Operation Canceled */
+pub const ENOKEY: ::c_int = 126; /* Required key not available */
+pub const EKEYEXPIRED: ::c_int = 127; /* Key has expired */
+pub const EKEYREVOKED: ::c_int = 128; /* Key has been revoked */
+pub const EKEYREJECTED: ::c_int = 129; /* Key was rejected by service */
+pub const EOWNERDEAD: ::c_int = 130; /* Owner died */
+pub const ENOTRECOVERABLE: ::c_int = 131; /* State not recoverable */
 
 // fcntl.h
 pub const F_DUPFD: ::c_int = 0;
@@ -281,7 +412,7 @@ pub const F_SETFD: ::c_int = 2;
 pub const F_GETFL: ::c_int = 3;
 pub const F_SETFL: ::c_int = 4;
 // TODO: relibc {
-    pub const F_DUPFD_CLOEXEC: ::c_int = ::F_DUPFD;
+pub const F_DUPFD_CLOEXEC: ::c_int = ::F_DUPFD;
 // }
 pub const FD_CLOEXEC: ::c_int = 0x0100_0000;
 pub const O_RDONLY: ::c_int = 0x0001_0000;
@@ -310,25 +441,25 @@ pub const EAI_SYSTEM: ::c_int = -11;
 
 // netinet/in.h
 // TODO: relibc {
-    pub const IP_TTL: ::c_int = 2;
-    pub const IPV6_UNICAST_HOPS: ::c_int = 16;
-    pub const IPV6_MULTICAST_IF: ::c_int = 17;
-    pub const IPV6_MULTICAST_HOPS: ::c_int = 18;
-    pub const IPV6_MULTICAST_LOOP: ::c_int = 19;
-    pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20;
-    pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21;
-    pub const IPV6_V6ONLY: ::c_int = 26;
-    pub const IP_MULTICAST_IF: ::c_int = 32;
-    pub const IP_MULTICAST_TTL: ::c_int = 33;
-    pub const IP_MULTICAST_LOOP: ::c_int = 34;
-    pub const IP_ADD_MEMBERSHIP: ::c_int = 35;
-    pub const IP_DROP_MEMBERSHIP: ::c_int = 36;
+pub const IP_TTL: ::c_int = 2;
+pub const IPV6_UNICAST_HOPS: ::c_int = 16;
+pub const IPV6_MULTICAST_IF: ::c_int = 17;
+pub const IPV6_MULTICAST_HOPS: ::c_int = 18;
+pub const IPV6_MULTICAST_LOOP: ::c_int = 19;
+pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20;
+pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21;
+pub const IPV6_V6ONLY: ::c_int = 26;
+pub const IP_MULTICAST_IF: ::c_int = 32;
+pub const IP_MULTICAST_TTL: ::c_int = 33;
+pub const IP_MULTICAST_LOOP: ::c_int = 34;
+pub const IP_ADD_MEMBERSHIP: ::c_int = 35;
+pub const IP_DROP_MEMBERSHIP: ::c_int = 36;
 // }
 
 // netinet/tcp.h
 pub const TCP_NODELAY: ::c_int = 1;
 // TODO: relibc {
-    pub const TCP_KEEPIDLE: ::c_int = 1;
+pub const TCP_KEEPIDLE: ::c_int = 1;
 // }
 
 // poll.h
@@ -345,7 +476,7 @@ pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
 pub const PTHREAD_MUTEX_INITIALIZER: ::pthread_mutex_t = -1isize as *mut _;
 pub const PTHREAD_COND_INITIALIZER: ::pthread_cond_t = -1isize as *mut _;
 pub const PTHREAD_RWLOCK_INITIALIZER: ::pthread_rwlock_t = -1isize as *mut _;
-pub const PTHREAD_STACK_MIN : ::size_t = 4096;
+pub const PTHREAD_STACK_MIN: ::size_t = 4096;
 
 // signal.h
 pub const SIG_BLOCK: ::c_int = 0;
@@ -384,6 +515,15 @@ pub const SIGPWR: ::c_int = 30;
 pub const SIGSYS: ::c_int = 31;
 pub const NSIG: ::c_int = 32;
 
+pub const SA_NOCLDSTOP: ::c_ulong = 0x00000001;
+pub const SA_NOCLDWAIT: ::c_ulong = 0x00000002;
+pub const SA_SIGINFO: ::c_ulong = 0x00000004;
+pub const SA_RESTORER: ::c_ulong = 0x04000000;
+pub const SA_ONSTACK: ::c_ulong = 0x08000000;
+pub const SA_RESTART: ::c_ulong = 0x10000000;
+pub const SA_NODEFER: ::c_ulong = 0x40000000;
+pub const SA_RESETHAND: ::c_ulong = 0x80000000;
+
 // sys/epoll.h
 pub const EPOLL_CLOEXEC: ::c_int = 0x0100_0000;
 pub const EPOLL_CTL_ADD: ::c_int = 1;
@@ -434,8 +574,8 @@ pub const EXIT_FAILURE: ::c_int = 1;
 
 // sys/ioctl.h
 // TODO: relibc {
-    pub const FIONBIO: ::c_ulong = 0x5421;
-    pub const FIOCLEX: ::c_ulong = 0x5451;
+pub const FIONBIO: ::c_ulong = 0x5421;
+pub const FIOCLEX: ::c_ulong = 0x5451;
 // }
 pub const TCGETS: ::c_ulong = 0x5401;
 pub const TCSETS: ::c_ulong = 0x5402;
@@ -472,6 +612,17 @@ pub const SOL_SOCKET: ::c_int = 1;
 
 // sys/wait.h
 pub const WNOHANG: ::c_int = 1;
+pub const WUNTRACED: ::c_int = 2;
+
+pub const WSTOPPED: ::c_int = 2;
+pub const WEXITED: ::c_int = 4;
+pub const WCONTINUED: ::c_int = 8;
+pub const WNOWAIT: ::c_int = 0x0100_0000;
+
+pub const __WNOTHREAD: ::c_int = 0x2000_0000;
+pub const __WALL: ::c_int = 0x4000_0000;
+#[allow(overflowing_literals)]
+pub const __WCLONE: ::c_int = 0x8000_0000;
 
 // termios.h
 pub const NCCS: usize = 32;
@@ -481,7 +632,34 @@ pub const CLOCK_REALTIME: ::c_int = 1;
 pub const CLOCK_MONOTONIC: ::c_int = 4;
 
 // unistd.h
+// POSIX.1 {
+pub const _SC_ARG_MAX: ::c_int = 0;
+pub const _SC_CHILD_MAX: ::c_int = 1;
+pub const _SC_CLK_TCK: ::c_int = 2;
+pub const _SC_NGROUPS_MAX: ::c_int = 3;
+pub const _SC_OPEN_MAX: ::c_int = 4;
+pub const _SC_STREAM_MAX: ::c_int = 5;
+pub const _SC_TZNAME_MAX: ::c_int = 6;
+// ...
+pub const _SC_VERSION: ::c_int = 29;
 pub const _SC_PAGESIZE: ::c_int = 30;
+pub const _SC_PAGE_SIZE: ::c_int = 30;
+// ...
+pub const _SC_RE_DUP_MAX: ::c_int = 44;
+// ...
+pub const _SC_LOGIN_NAME_MAX: ::c_int = 71;
+pub const _SC_TTY_NAME_MAX: ::c_int = 72;
+// ...
+pub const _SC_SYMLOOP_MAX: ::c_int = 173;
+// ...
+pub const _SC_HOST_NAME_MAX: ::c_int = 180;
+// } POSIX.1
+
+pub const F_OK: ::c_int = 0;
+pub const R_OK: ::c_int = 4;
+pub const W_OK: ::c_int = 2;
+pub const X_OK: ::c_int = 1;
+
 pub const SEEK_SET: ::c_int = 0;
 pub const SEEK_CUR: ::c_int = 1;
 pub const SEEK_END: ::c_int = 2;
@@ -489,109 +667,327 @@ pub const STDIN_FILENO: ::c_int = 0;
 pub const STDOUT_FILENO: ::c_int = 1;
 pub const STDERR_FILENO: ::c_int = 2;
 
-// wait.h
-pub fn WIFSTOPPED(status: ::c_int) -> bool {
-    (status & 0xff) == 0x7f
-}
+pub const _PC_LINK_MAX: ::c_int = 0;
+pub const _PC_MAX_CANON: ::c_int = 1;
+pub const _PC_MAX_INPUT: ::c_int = 2;
+pub const _PC_NAME_MAX: ::c_int = 3;
+pub const _PC_PATH_MAX: ::c_int = 4;
+pub const _PC_PIPE_BUF: ::c_int = 5;
+pub const _PC_CHOWN_RESTRICTED: ::c_int = 6;
+pub const _PC_NO_TRUNC: ::c_int = 7;
+pub const _PC_VDISABLE: ::c_int = 8;
+pub const _PC_SYNC_IO: ::c_int = 9;
+pub const _PC_ASYNC_IO: ::c_int = 10;
+pub const _PC_PRIO_IO: ::c_int = 11;
+pub const _PC_SOCK_MAXBUF: ::c_int = 12;
+pub const _PC_FILESIZEBITS: ::c_int = 13;
+pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14;
+pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15;
+pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16;
+pub const _PC_REC_XFER_ALIGN: ::c_int = 17;
+pub const _PC_ALLOC_SIZE_MIN: ::c_int = 18;
+pub const _PC_SYMLINK_MAX: ::c_int = 19;
+pub const _PC_2_SYMLINKS: ::c_int = 20;
 
-pub fn WSTOPSIG(status: ::c_int) -> ::c_int {
-    (status >> 8) & 0xff
-}
+// wait.h
+f! {
+    pub fn WIFSTOPPED(status: ::c_int) -> bool {
+        (status & 0xff) == 0x7f
+    }
 
-pub fn WIFCONTINUED(status: ::c_int) -> bool {
-    status == 0xffff
-}
+    pub fn WSTOPSIG(status: ::c_int) -> ::c_int {
+        (status >> 8) & 0xff
+    }
 
-pub fn WIFSIGNALED(status: ::c_int) -> bool {
-    ((status & 0x7f) + 1) as i8 >= 2
-}
+    pub fn WIFCONTINUED(status: ::c_int) -> bool {
+        status == 0xffff
+    }
 
-pub fn WTERMSIG(status: ::c_int) -> ::c_int {
-    status & 0x7f
-}
+    pub fn WIFSIGNALED(status: ::c_int) -> bool {
+        ((status & 0x7f) + 1) as i8 >= 2
+    }
 
-pub fn WIFEXITED(status: ::c_int) -> bool {
-    (status & 0x7f) == 0
-}
+    pub fn WTERMSIG(status: ::c_int) -> ::c_int {
+        status & 0x7f
+    }
 
-pub fn WEXITSTATUS(status: ::c_int) -> ::c_int {
-    (status >> 8) & 0xff
-}
+    pub fn WIFEXITED(status: ::c_int) -> bool {
+        (status & 0x7f) == 0
+    }
 
-pub fn WCOREDUMP(status: ::c_int) -> bool {
-    (status & 0x80) != 0
-}
+    pub fn WEXITSTATUS(status: ::c_int) -> ::c_int {
+        (status >> 8) & 0xff
+    }
 
-// intentionally not public, only used for fd_set
-cfg_if! {
-    if #[cfg(target_pointer_width = "32")] {
-        const ULONG_SIZE: usize = 32;
-    } else if #[cfg(target_pointer_width = "64")] {
-        const ULONG_SIZE: usize = 64;
-    } else {
-        // Unknown target_pointer_width
+    pub fn WCOREDUMP(status: ::c_int) -> bool {
+        (status & 0x80) != 0
     }
 }
 
 extern {
-    pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int;
-    pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int;
-
+    // errno.h
+    pub fn __errno_location() -> *mut ::c_int;
     pub fn strerror_r(errnum: ::c_int, buf: *mut c_char,
                       buflen: ::size_t) -> ::c_int;
-    pub fn __errno_location() -> *mut ::c_int;
+
+    // unistd.h
+    pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int;
 
     // malloc.h
     pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
 
     // pthread.h
-    pub fn pthread_atfork(prepare: ::Option<unsafe extern fn()>,
-                          parent: ::Option<unsafe extern fn()>,
-                          child: ::Option<unsafe extern fn()>) -> ::c_int;
-    pub fn pthread_create(tid: *mut ::pthread_t,
-                          attr: *const ::pthread_attr_t,
-                          start: extern fn(*mut ::c_void) -> *mut ::c_void,
-                          arg: *mut ::c_void) -> ::c_int;
-    pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t,
-                                     clock_id: ::clockid_t) -> ::c_int;
+    pub fn pthread_atfork(
+        prepare: ::Option<unsafe extern fn()>,
+        parent: ::Option<unsafe extern fn()>,
+        child: ::Option<unsafe extern fn()>,
+    ) -> ::c_int;
+    pub fn pthread_create(
+        tid: *mut ::pthread_t,
+        attr: *const ::pthread_attr_t,
+        start: extern fn(*mut ::c_void) -> *mut ::c_void,
+        arg: *mut ::c_void,
+    ) -> ::c_int;
+    pub fn pthread_condattr_setclock(
+        attr: *mut pthread_condattr_t,
+        clock_id: ::clockid_t,
+    ) -> ::c_int;
+
+    // pwd.h
+    pub fn getpwuid_r(uid: ::uid_t,
+                      pwd: *mut passwd,
+                      buf: *mut ::c_char,
+                      buflen: ::size_t,
+                      result: *mut *mut passwd) -> ::c_int;
 
     // signal.h
-    pub fn pthread_sigmask(how: ::c_int,
-                           set: *const ::sigset_t,
-                           oldset: *mut ::sigset_t) -> ::c_int;
+    pub fn pthread_sigmask(
+        how: ::c_int,
+        set: *const ::sigset_t,
+        oldset: *mut ::sigset_t,
+    ) -> ::c_int;
 
     // sys/epoll.h
     pub fn epoll_create(size: ::c_int) -> ::c_int;
     pub fn epoll_create1(flags: ::c_int) -> ::c_int;
-    pub fn epoll_wait(epfd: ::c_int,
-                      events: *mut ::epoll_event,
-                      maxevents: ::c_int,
-                      timeout: ::c_int) -> ::c_int;
-    pub fn epoll_ctl(epfd: ::c_int,
-                     op: ::c_int,
-                     fd: ::c_int,
-                     event: *mut ::epoll_event) -> ::c_int;
+    pub fn epoll_wait(
+        epfd: ::c_int,
+        events: *mut ::epoll_event,
+        maxevents: ::c_int,
+        timeout: ::c_int,
+    ) -> ::c_int;
+    pub fn epoll_ctl(
+        epfd: ::c_int,
+        op: ::c_int,
+        fd: ::c_int,
+        event: *mut ::epoll_event,
+    ) -> ::c_int;
 
     // sys/ioctl.h
     pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int;
 
+    // sys/resource.h
+    pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int;
+    pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int;
+
     // sys/socket.h
-    pub fn bind(socket: ::c_int, address: *const ::sockaddr,
-                address_len: ::socklen_t) -> ::c_int;
-    pub fn recvfrom(socket: ::c_int, buf: *mut ::c_void, len: ::size_t,
-                    flags: ::c_int, addr: *mut ::sockaddr,
-                    addrlen: *mut ::socklen_t) -> ::ssize_t;
+    pub fn bind(
+        socket: ::c_int,
+        address: *const ::sockaddr,
+        address_len: ::socklen_t,
+    ) -> ::c_int;
+    pub fn recvfrom(
+        socket: ::c_int,
+        buf: *mut ::c_void,
+        len: ::size_t,
+        flags: ::c_int,
+        addr: *mut ::sockaddr,
+        addrlen: *mut ::socklen_t,
+    ) -> ::ssize_t;
+
+    // sys/stat.h
+    pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int;
 
     // sys/uio.h
-    pub fn readv(fd: ::c_int,
-                 iov: *const ::iovec,
-                 iovcnt: ::c_int) -> ::ssize_t;
-    pub fn writev(fd: ::c_int,
-                  iov: *const ::iovec,
-                  iovcnt: ::c_int) -> ::ssize_t;
+    pub fn readv(
+        fd: ::c_int,
+        iov: *const ::iovec,
+        iovcnt: ::c_int,
+    ) -> ::ssize_t;
+    pub fn writev(
+        fd: ::c_int,
+        iov: *const ::iovec,
+        iovcnt: ::c_int,
+    ) -> ::ssize_t;
+
+    // sys/utsname.h
+    pub fn uname(utsname: *mut utsname) -> ::c_int;
 
     // time.h
     pub fn gettimeofday(tp: *mut ::timeval,
                         tz: *mut ::timezone) -> ::c_int;
     pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
 }
+
+cfg_if! {
+    if #[cfg(feature = "extra_traits")] {
+        impl PartialEq for dirent {
+            fn eq(&self, other: &dirent) -> bool {
+                self.d_ino == other.d_ino
+                    && self.d_off == other.d_off
+                    && self.d_reclen == other.d_reclen
+                    && self.d_type == other.d_type
+                    && self
+                    .d_name
+                    .iter()
+                    .zip(other.d_name.iter())
+                    .all(|(a,b)| a == b)
+            }
+        }
+
+        impl Eq for dirent {}
+
+        impl ::fmt::Debug for dirent {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("dirent")
+                    .field("d_ino", &self.d_ino)
+                    .field("d_off", &self.d_off)
+                    .field("d_reclen", &self.d_reclen)
+                    .field("d_type", &self.d_type)
+                // FIXME: .field("d_name", &self.d_name)
+                    .finish()
+            }
+        }
+
+        impl ::hash::Hash for dirent {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.d_ino.hash(state);
+                self.d_off.hash(state);
+                self.d_reclen.hash(state);
+                self.d_type.hash(state);
+                self.d_name.hash(state);
+            }
+        }
+
+        impl PartialEq for sockaddr_un {
+            fn eq(&self, other: &sockaddr_un) -> bool {
+                self.sun_family == other.sun_family
+                    && self
+                    .sun_path
+                    .iter()
+                    .zip(other.sun_path.iter())
+                    .all(|(a,b)| a == b)
+            }
+        }
+
+        impl Eq for sockaddr_un {}
+
+        impl ::fmt::Debug for sockaddr_un {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("sockaddr_un")
+                    .field("sun_family", &self.sun_family)
+                // FIXME: .field("sun_path", &self.sun_path)
+                    .finish()
+            }
+        }
+
+        impl ::hash::Hash for sockaddr_un {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.sun_family.hash(state);
+                self.sun_path.hash(state);
+            }
+        }
+
+        impl PartialEq for sockaddr_storage {
+            fn eq(&self, other: &sockaddr_storage) -> bool {
+                self.ss_family == other.ss_family
+                    && self.__ss_align == self.__ss_align
+                    && self
+                    .__ss_padding
+                    .iter()
+                    .zip(other.__ss_padding.iter())
+                    .all(|(a,b)| a == b)
+            }
+        }
+
+        impl Eq for sockaddr_storage {}
+
+        impl ::fmt::Debug for sockaddr_storage {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("sockaddr_storage")
+                    .field("ss_family", &self.ss_family)
+                    .field("__ss_align", &self.__ss_align)
+                // FIXME: .field("__ss_padding", &self.__ss_padding)
+                    .finish()
+            }
+        }
+
+        impl ::hash::Hash for sockaddr_storage {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.ss_family.hash(state);
+                self.__ss_padding.hash(state);
+                self.__ss_align.hash(state);
+            }
+        }
+
+        impl PartialEq for utsname {
+            fn eq(&self, other: &utsname) -> bool {
+                self.sysname
+                    .iter()
+                    .zip(other.sysname.iter())
+                    .all(|(a, b)| a == b)
+                    && self
+                    .nodename
+                    .iter()
+                    .zip(other.nodename.iter())
+                    .all(|(a, b)| a == b)
+                    && self
+                    .release
+                    .iter()
+                    .zip(other.release.iter())
+                    .all(|(a, b)| a == b)
+                    && self
+                    .version
+                    .iter()
+                    .zip(other.version.iter())
+                    .all(|(a, b)| a == b)
+                    && self
+                    .machine
+                    .iter()
+                    .zip(other.machine.iter())
+                    .all(|(a, b)| a == b)
+                    && self
+                    .domainname
+                    .iter()
+                    .zip(other.domainname.iter())
+                    .all(|(a, b)| a == b)
+            }
+        }
+
+        impl Eq for utsname {}
+
+        impl ::fmt::Debug for utsname {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                f.debug_struct("utsname")
+                // FIXME: .field("sysname", &self.sysname)
+                // FIXME: .field("nodename", &self.nodename)
+                // FIXME: .field("release", &self.release)
+                // FIXME: .field("version", &self.version)
+                // FIXME: .field("machine", &self.machine)
+                // FIXME: .field("domainname", &self.domainname)
+                    .finish()
+            }
+        }
+
+        impl ::hash::Hash for utsname {
+            fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+                self.sysname.hash(state);
+                self.nodename.hash(state);
+                self.release.hash(state);
+                self.version.hash(state);
+                self.machine.hash(state);
+                self.domainname.hash(state);
+            }
+        }
+    }
+}